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 <cstdio>
50#include <ctime>
51#include <cstring>
52
53
54////////////////////////////////////////////////////////////////////////////////
55
57 : fAuthType(kNoAuth), fHost("NoHost")
58{
59}
60
61////////////////////////////////////////////////////////////////////////////////
62/// Default constructor
63
66 const TString& accessKey, const TString& secretKey)
67{
68 fVerb = httpVerb;
69 fHost = host;
70 fBucket = bucket;
71 fObjectKey = objectKey;
72 fAuthType = authType;
73 fAccessKey = accessKey;
74 fSecretKey = secretKey;
75}
76
77////////////////////////////////////////////////////////////////////////////////
78/// Copy constructor
79
81 : TObject(r)
82{
83 fVerb = r.fVerb;
84 fHost = r.fHost;
85 fBucket = r.fBucket;
86 fObjectKey = r.fObjectKey;
87 fAuthType = r.fAuthType;
88 fAccessKey = r.fAccessKey;
89 fSecretKey = r.fSecretKey;
90 fTimeStamp = r.fTimeStamp;
91}
92
93////////////////////////////////////////////////////////////////////////////////
94/// Returns this request's signature
95
97{
98 // Please note, the order of the fields used for computing
99 // the signature is important. Make sure that the changes you
100 // make are compatible with the reference documentation.
101 //
102 // Refs:
103 // AMAZON http://awsdocs.s3.amazonaws.com/S3/latest/s3-qrc.pdf
104 // GOOGLE: http://code.google.com/apis/storage/docs/reference/v1/developer-guidev1.html#authentication
105
106 TString toSign = TString::Format("%s\n\n\n%s\n", // empty Content-MD5 and Content-Type
107 (const char*)HTTPVerbToTString(httpVerb),
108 (const char*)fTimeStamp);
109 if (fAuthType == kGoogle) {
110 // Must use API version 1. Google Storage API v2 only
111 // accepts OAuth authentication.
112 // This header is not strictly needed but if used for computing
113 // the signature, the request must contain it as a header
114 // (see method MakeAuthHeader)
115 // Ref: https://developers.google.com/storage/docs/reference/v1/apiversion1
116 toSign += "x-goog-api-version:1\n"; // Lowercase, no spaces around ':'
117 }
118
119 if (fAuthType == kAmazon) {
120 if (!fSessionToken.IsNull()) {
121 toSign += "x-amz-security-token:" + fSessionToken + "\n";
122 }
123 }
124
125 toSign += "/" + fBucket + fObjectKey;
126
127 unsigned char digest[SHA_DIGEST_LENGTH] = {0};
128#if defined(MAC_OS_X_VERSION_10_7)
129 CCHmac(kCCHmacAlgSHA1, fSecretKey.Data(), fSecretKey.Length() , (unsigned char *)toSign.Data(), toSign.Length(), digest);
130#else
131 unsigned int *sd = NULL;
132 HMAC(EVP_sha1(), fSecretKey.Data(), fSecretKey.Length() , (unsigned char *)toSign.Data(), toSign.Length(), digest, sd);
133#endif
134
135 return TBase64::Encode((const char *)digest, SHA_DIGEST_LENGTH);
136}
137
138////////////////////////////////////////////////////////////////////////////////
139
141{
142 switch (httpVerb) {
143 case kGET: return TString("GET");
144 case kPOST: return TString("POST");
145 case kPUT: return TString("PUT");
146 case kDELETE: return TString("DELETE");
147 case kHEAD: return TString("HEAD");
148 case kCOPY: return TString("COPY");
149 default: return TString("");
150 }
151}
152
153////////////////////////////////////////////////////////////////////////////////
154/// Sets this request's time stamp according to:
155/// http://code.google.com/apis/storage/docs/reference-headers.html#date
156
158{
159 time_t now = time(NULL);
160 char result[128];
161 struct tm dateFormat;
162#ifdef R__WIN32
164 strftime(result, sizeof(result), "%a, %d %b %Y %H:%M:%S GMT", &dateFormat);
165#else
166 strftime(result, sizeof(result), "%a, %d %b %Y %H:%M:%S GMT",
168#endif
169 fTimeStamp = result;
170 return *this;
171}
172
173////////////////////////////////////////////////////////////////////////////////
174/// Returns the first line of a HTTP request for this object. Note that since
175/// we don't use the virtual host syntax which is supported by Amazon, we
176/// must include the bucket name in thr resource. For example, we don't use
177/// http://mybucket.s3.amazonaws.com/path/to/my/file but instead
178/// http://s3.amazonaws.com/mybucket/path/to/my/file so the HTTP request
179/// will be of the form "GET /mybucket/path/to/my/file HTTP/1.1"
180/// Also note that the path must include the leading '/'.
181
183{
184 return TString::Format("%s /%s%s HTTP/1.1",
185 (const char*)HTTPVerbToTString(httpVerb),
186 (const char*)fBucket,
187 (const char*)fObjectKey);
188}
189
190////////////////////////////////////////////////////////////////////////////////
191/// Returns the 'Host' header to include in the HTTP request.
192
194{
195 return "Host: " + fHost;
196}
197
198////////////////////////////////////////////////////////////////////////////////
199/// Returns the date header for this HTTP request
200
202{
203 return "Date: " + fTimeStamp;
204}
205
206////////////////////////////////////////////////////////////////////////////////
207/// Returns the session security token header for this HTTP request
208
210{
211 if (fAuthType != kAmazon)
212 return "";
213
214 if (fSessionToken.IsNull())
215 return "";
216
217 return TString::Format("x-amz-security-token: %s",
218 (const char*) fSessionToken.Data());
219}
220
221////////////////////////////////////////////////////////////////////////////////
222/// Returns the authentication prefix
223
225{
226 switch (fAuthType) {
227 case kNoAuth: return "";
228 case kGoogle: return "GOOG1";
229 case kAmazon:
230 default: return "AWS";
231 }
232}
233
234////////////////////////////////////////////////////////////////////////////////
235/// Returns the authentication header for this HTTP request
236
238{
239 if (fAuthType == kNoAuth)
240 return "";
241
242 return TString::Format("Authorization: %s %s:%s%s",
243 (const char*)MakeAuthPrefix(),
244 (const char*)fAccessKey,
245 (const char*)ComputeSignature(httpVerb),
246 (fAuthType == kGoogle) ? "\r\nx-goog-api-version: 1" : "");
247}
248
249////////////////////////////////////////////////////////////////////////////////
250/// Returns the HTTP request ready to be sent to the server
251
253{
254 // Set time stamp before computing this request's signature. The signature
255 // includes the date.
256 SetTimeStamp();
257 TString request = TString::Format("%s\r\n%s\r\n%s\r\n",
258 (const char*)MakeRequestLine(httpVerb),
259 (const char*)MakeHostHeader(),
260 (const char*)MakeDateHeader());
261 TString tokenHeader = MakeTokenHeader();
262 if (!tokenHeader.IsNull())
263 request += tokenHeader + "\r\n";
264 TString authHeader = MakeAuthHeader(httpVerb);
265 if (!authHeader.IsNull())
266 request += authHeader + "\r\n";
267 if (appendCRLF)
268 request += "\r\n";
269 return request;
270}
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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
TString MakeAuthPrefix() const
Returns the authentication prefix.
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 MakeAuthHeader(TS3HTTPRequest::EHTTPVerb httpVerb) const
Returns the authentication 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 MakeDateHeader() const
Returns the date header for this HTTP request.
TString ComputeSignature(TS3HTTPRequest::EHTTPVerb httpVerb) const
Returns this request's signature.
TString MakeTokenHeader() const
Returns the session security token header for this HTTP request.
TString MakeRequestLine(TS3HTTPRequest::EHTTPVerb httpVerb) const
Returns the first line of a HTTP request for this object.
TString MakeHostHeader() const
Returns the 'Host' header to include in the HTTP request.
static TString Encode(const char *data)
Transform data into a null terminated base64 string.
Definition TBase64.cxx:106
Mother of all ROOT objects.
Definition TObject.h:42
Basic string class.
Definition TString.h:138
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:2384