Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TS3HTTPRequest.cxx
Go to the documentation of this file.
1// @(#)root/net:$Id$
2// Author: Fabio Hernandez 30/01/2013
3// based on an initial version by Marcelo Sousa (class THTTPMessage)
4
5/*************************************************************************
6 * Copyright (C) 1995-2011, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13//////////////////////////////////////////////////////////////////////////
14// //
15// TS3HTTPRequest //
16// //
17// An object of this class represents an HTTP request extended to be //
18// compatible with Amazon's S3 protocol. //
19// Specifically, such a request contains an 'Authorization' header with //
20// information used by the S3 server for authenticating this request. //
21// The authentication information is computed based on a pair of access //
22// key and secret key which are both provided to the user by the S3 //
23// service provider (e.g. Amazon, Google, etc.). //
24// The secret key is used to compute a signature of selected fields in //
25// the request. The algorithm for computing the signature is documented //
26// in: //
27// //
28// Google storage: //
29// http://code.google.com/apis/storage/docs/reference/v1/developer-guidev1.html#authentication
30// //
31// Amazon: //
32// http://docs.aws.amazon.com/AmazonS3/latest/dev/S3_Authentication2.html
33// //
34//////////////////////////////////////////////////////////////////////////
35
36#include "TS3HTTPRequest.h"
37#include "TBase64.h"
38#if defined(MAC_OS_X_VERSION_10_7)
39#include <CommonCrypto/CommonHMAC.h>
40#define SHA_DIGEST_LENGTH 20
41#else
42#include <openssl/sha.h>
43#include <openssl/hmac.h>
44#include <openssl/evp.h>
45#include <openssl/bio.h>
46#include <openssl/buffer.h>
47#endif
48
49#include <stdio.h>
50#include <time.h>
51#include <string.h>
52
54
55////////////////////////////////////////////////////////////////////////////////
56
58 : fAuthType(kNoAuth), fHost("NoHost")
59{
60}
61
62////////////////////////////////////////////////////////////////////////////////
63/// Default constructor
64
66 const TString& bucket, const TString& objectKey, EAuthType authType,
67 const TString& accessKey, const TString& secretKey)
68{
69 fVerb = httpVerb;
70 fHost = host;
71 fBucket = bucket;
72 fObjectKey = objectKey;
73 fAuthType = authType;
74 fAccessKey = accessKey;
75 fSecretKey = secretKey;
76}
77
78////////////////////////////////////////////////////////////////////////////////
79/// Copy constructor
80
82 : TObject(r)
83{
84 fVerb = r.fVerb;
85 fHost = r.fHost;
86 fBucket = r.fBucket;
87 fObjectKey = r.fObjectKey;
88 fAuthType = r.fAuthType;
89 fAccessKey = r.fAccessKey;
90 fSecretKey = r.fSecretKey;
91 fTimeStamp = r.fTimeStamp;
92}
93
94////////////////////////////////////////////////////////////////////////////////
95/// Returns this request's signature
96
98{
99 // Please note, the order of the fields used for computing
100 // the signature is important. Make sure that the changes you
101 // make are compatible with the reference documentation.
102 //
103 // Refs:
104 // AMAZON http://awsdocs.s3.amazonaws.com/S3/latest/s3-qrc.pdf
105 // GOOGLE: http://code.google.com/apis/storage/docs/reference/v1/developer-guidev1.html#authentication
106
107 TString toSign = TString::Format("%s\n\n\n%s\n", // empty Content-MD5 and Content-Type
108 (const char*)HTTPVerbToTString(httpVerb),
109 (const char*)fTimeStamp);
110 if (fAuthType == kGoogle) {
111 // Must use API version 1. Google Storage API v2 only
112 // accepts OAuth authentication.
113 // This header is not strictly needed but if used for computing
114 // the signature, the request must contain it as a header
115 // (see method MakeAuthHeader)
116 // Ref: https://developers.google.com/storage/docs/reference/v1/apiversion1
117 toSign += "x-goog-api-version:1\n"; // Lowercase, no spaces around ':'
118 }
119
120 if (fAuthType == kAmazon) {
121 if (!fSessionToken.IsNull()) {
122 toSign += "x-amz-security-token:" + fSessionToken + "\n";
123 }
124 }
125
126 toSign += "/" + fBucket + fObjectKey;
127
128 unsigned char digest[SHA_DIGEST_LENGTH] = {0};
129#if defined(MAC_OS_X_VERSION_10_7)
130 CCHmac(kCCHmacAlgSHA1, fSecretKey.Data(), fSecretKey.Length() , (unsigned char *)toSign.Data(), toSign.Length(), digest);
131#else
132 unsigned int *sd = NULL;
133 HMAC(EVP_sha1(), fSecretKey.Data(), fSecretKey.Length() , (unsigned char *)toSign.Data(), toSign.Length(), digest, sd);
134#endif
135
136 return TBase64::Encode((const char *)digest, SHA_DIGEST_LENGTH);
137}
138
139////////////////////////////////////////////////////////////////////////////////
140
142{
143 switch (httpVerb) {
144 case kGET: return TString("GET");
145 case kPOST: return TString("POST");
146 case kPUT: return TString("PUT");
147 case kDELETE: return TString("DELETE");
148 case kHEAD: return TString("HEAD");
149 case kCOPY: return TString("COPY");
150 default: return TString("");
151 }
152}
153
154////////////////////////////////////////////////////////////////////////////////
155/// Sets this request's time stamp according to:
156/// http://code.google.com/apis/storage/docs/reference-headers.html#date
157
159{
160 time_t now = time(NULL);
161 char result[128];
162 struct tm dateFormat;
163 strftime(result, sizeof(result), "%a, %d %b %Y %H:%M:%S GMT",
164 gmtime_r(&now, &dateFormat));
166 return *this;
167}
168
169////////////////////////////////////////////////////////////////////////////////
170/// Returns the first line of a HTTP request for this object. Note that since
171/// we don't use the virtual host syntax which is supported by Amazon, we
172/// must include the bucket name in thr resource. For example, we don't use
173/// http://mybucket.s3.amazonaws.com/path/to/my/file but instead
174/// http://s3.amazonaws.com/mybucket/path/to/my/file so the HTTP request
175/// will be of the form "GET /mybucket/path/to/my/file HTTP/1.1"
176/// Also note that the path must include the leading '/'.
177
179{
180 return TString::Format("%s /%s%s HTTP/1.1",
181 (const char*)HTTPVerbToTString(httpVerb),
182 (const char*)fBucket,
183 (const char*)fObjectKey);
184}
185
186////////////////////////////////////////////////////////////////////////////////
187/// Returns the 'Host' header to include in the HTTP request.
188
190{
191 return "Host: " + fHost;
192}
193
194////////////////////////////////////////////////////////////////////////////////
195/// Returns the date header for this HTTP request
196
198{
199 return "Date: " + fTimeStamp;
200}
201
202////////////////////////////////////////////////////////////////////////////////
203/// Returns the session security token header for this HTTP request
204
206{
207 if (fAuthType != kAmazon)
208 return "";
209
210 if (fSessionToken.IsNull())
211 return "";
212
213 return TString::Format("x-amz-security-token: %s",
214 (const char*) fSessionToken.Data());
215}
216
217////////////////////////////////////////////////////////////////////////////////
218/// Returns the authentication prefix
219
221{
222 switch (fAuthType) {
223 case kNoAuth: return "";
224 case kGoogle: return "GOOG1";
225 case kAmazon:
226 default: return "AWS";
227 }
228}
229
230////////////////////////////////////////////////////////////////////////////////
231/// Returns the authentication header for this HTTP request
232
234{
235 if (fAuthType == kNoAuth)
236 return "";
237
238 return TString::Format("Authorization: %s %s:%s%s",
239 (const char*)MakeAuthPrefix(),
240 (const char*)fAccessKey,
241 (const char*)ComputeSignature(httpVerb),
242 (fAuthType == kGoogle) ? "\r\nx-goog-api-version: 1" : "");
243}
244
245////////////////////////////////////////////////////////////////////////////////
246/// Returns the HTTP request ready to be sent to the server
247
249{
250 // Set time stamp before computing this request's signature. The signature
251 // includes the date.
252 SetTimeStamp();
253 TString request = TString::Format("%s\r\n%s\r\n%s\r\n",
254 (const char*)MakeRequestLine(httpVerb),
255 (const char*)MakeHostHeader(),
256 (const char*)MakeDateHeader());
257 TString tokenHeader = MakeTokenHeader();
258 if (!tokenHeader.IsNull())
259 request += tokenHeader + "\r\n";
260 TString authHeader = MakeAuthHeader(httpVerb);
261 if (!authHeader.IsNull())
262 request += authHeader + "\r\n";
263 if (appendCRLF)
264 request += "\r\n";
265 return request;
266}
#define ClassImp(name)
Definition Rtypes.h:382
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
static TString Encode(const char *data)
Transform data into a null terminated base64 string.
Definition TBase64.cxx:107
Mother of all ROOT objects.
Definition TObject.h:41
TString fSessionToken
TString GetRequest(TS3HTTPRequest::EHTTPVerb httpVerb, Bool_t appendCRLF=kTRUE)
Returns the HTTP request ready to be sent to the server.
TString HTTPVerbToTString(EHTTPVerb httpVerb) const
TString MakeAuthPrefix() const
Returns the authentication prefix.
EAuthType fAuthType
TString MakeTokenHeader() const
Returns the session security token header for this HTTP request.
TS3HTTPRequest & SetTimeStamp()
Sets this request's time stamp according to: http://code.google.com/apis/storage/docs/reference-heade...
TString ComputeSignature(TS3HTTPRequest::EHTTPVerb httpVerb) const
Returns this request's signature.
TString MakeRequestLine(TS3HTTPRequest::EHTTPVerb httpVerb) const
Returns the first line of a HTTP request for this object.
TString MakeAuthHeader(TS3HTTPRequest::EHTTPVerb httpVerb) const
Returns the authentication header for this HTTP request.
TString MakeHostHeader() const
Returns the 'Host' header to include in the HTTP request.
TString MakeDateHeader() const
Returns the date header for this HTTP request.
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
const char * Data() const
Definition TString.h:376
Bool_t IsNull() const
Definition TString.h:414
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2378