moved calc_signature to curl.cpp

git-svn-id: http://s3fs.googlecode.com/svn/trunk@380 df820570-a93a-0410-bd06-b72b767a4274
This commit is contained in:
ben.lemasurier@gmail.com 2011-08-31 20:36:40 +00:00
parent 8d941f42b5
commit 9fb05fba4f
4 changed files with 118 additions and 113 deletions

View File

@ -29,6 +29,11 @@
#include <syslog.h>
#include <pthread.h>
#include <curl/curl.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/md5.h>
#include <iostream>
#include <fstream>
#include <string>
@ -361,6 +366,113 @@ int my_curl_progress(
return 0;
}
/**
* Returns the Amazon AWS signature for the given parameters.
*
* @param method e.g., "GET"
* @param content_type e.g., "application/x-directory"
* @param date e.g., get_date()
* @param resource e.g., "/pub"
*/
string calc_signature(
string method, string content_type, string date, curl_slist* headers, string resource) {
int ret;
int bytes_written;
int offset;
int write_attempts = 0;
string Signature;
string StringToSign;
StringToSign += method + "\n";
StringToSign += "\n"; // md5
StringToSign += content_type + "\n";
StringToSign += date + "\n";
int count = 0;
if(headers != 0) {
do {
if(strncmp(headers->data, "x-amz", 5) == 0) {
++count;
StringToSign += headers->data;
StringToSign += 10; // linefeed
}
} while ((headers = headers->next) != 0);
}
StringToSign += resource;
const void* key = AWSSecretAccessKey.data();
int key_len = AWSSecretAccessKey.size();
const unsigned char* d = reinterpret_cast<const unsigned char*>(StringToSign.data());
int n = StringToSign.size();
unsigned int md_len;
unsigned char md[EVP_MAX_MD_SIZE];
HMAC(evp_md, key, key_len, d, n, md, &md_len);
BIO* b64 = BIO_new(BIO_f_base64());
BIO* bmem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, bmem);
offset = 0;
for(;;) {
bytes_written = BIO_write(b64, &(md[offset]), md_len);
write_attempts++;
// -1 indicates that an error occurred, or a temporary error, such as
// the server is busy, occurred and we need to retry later.
// BIO_write can do a short write, this code addresses this condition
if(bytes_written <= 0) {
// Indicates whether a temporary error occurred or a failure to
// complete the operation occurred
if ((ret = BIO_should_retry(b64))) {
// Wait until the write can be accomplished
if(write_attempts <= 10)
continue;
// Too many write attempts
syslog(LOG_ERR, "Failure during BIO_write, returning null String");
BIO_free_all(b64);
Signature.clear();
return Signature;
} else {
// If not a retry then it is an error
syslog(LOG_ERR, "Failure during BIO_write, returning null String");
BIO_free_all(b64);
Signature.clear();
return Signature;
}
}
// The write request succeeded in writing some Bytes
offset += bytes_written;
md_len -= bytes_written;
// If there is no more data to write, the request sending has been
// completed
if(md_len <= 0)
break;
}
// Flush the data
ret = BIO_flush(b64);
if ( ret <= 0) {
syslog(LOG_ERR, "Failure during BIO_flush, returning null String");
BIO_free_all(b64);
Signature.clear();
return Signature;
}
BUF_MEM *bptr;
BIO_get_mem_ptr(b64, &bptr);
Signature.resize(bptr->length - 1);
memcpy(&Signature[0], bptr->data, bptr->length-1);
BIO_free_all(b64);
return Signature;
}
void locate_bundle(void) {
// See if environment variable CURL_CA_BUNDLE is set
// if so, check it, if it is a good path, then set the

View File

@ -21,6 +21,9 @@ extern time_t readwrite_timeout;
extern bool debug;
extern std::string program_name;
extern std::string ssl_verify_hostname;
extern std::string AWSSecretAccessKey;
static const EVP_MD* evp_md = EVP_sha1();
CURL *create_curl_handle(void);
void destroy_curl_handle(CURL *curl_handle);
@ -29,6 +32,8 @@ size_t WriteMemoryCallback(void *ptr, size_t blockSize, size_t numBlocks, void *
size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp);
int my_curl_progress(
void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
std::string calc_signature(
std::string method, std::string content_type, std::string date, curl_slist* headers, std::string resource);
void locate_bundle(void);
#endif // S3FS_CURL_H_

View File

@ -283,116 +283,6 @@ void free_mvnodes(MVNODE *head) {
return;
}
/**
* Returns the Amazon AWS signature for the given parameters.
*
* @param method e.g., "GET"
* @param content_type e.g., "application/x-directory"
* @param date e.g., get_date()
* @param resource e.g., "/pub"
*/
string calc_signature(
string method, string content_type, string date, curl_slist* headers, string resource) {
int ret;
int bytes_written;
int offset;
int write_attempts = 0;
string Signature;
string StringToSign;
StringToSign += method + "\n";
StringToSign += "\n"; // md5
StringToSign += content_type + "\n";
StringToSign += date + "\n";
int count = 0;
if(headers != 0) {
do {
if(strncmp(headers->data, "x-amz", 5) == 0) {
++count;
StringToSign += headers->data;
StringToSign += 10; // linefeed
}
} while ((headers = headers->next) != 0);
}
StringToSign += resource;
const void* key = AWSSecretAccessKey.data();
int key_len = AWSSecretAccessKey.size();
const unsigned char* d = reinterpret_cast<const unsigned char*>(StringToSign.data());
int n = StringToSign.size();
unsigned int md_len;
unsigned char md[EVP_MAX_MD_SIZE];
HMAC(evp_md, key, key_len, d, n, md, &md_len);
BIO* b64 = BIO_new(BIO_f_base64());
BIO* bmem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, bmem);
offset = 0;
for (;;) {
bytes_written = BIO_write(b64, &(md[offset]), md_len);
write_attempts++;
// -1 indicates that an error occurred, or a temporary error, such as
// the server is busy, occurred and we need to retry later.
// BIO_write can do a short write, this code addresses this condition
if (bytes_written <= 0) {
// Indicates whether a temporary error occurred or a failure to
// complete the operation occurred
if ((ret = BIO_should_retry(b64))) {
// Wait until the write can be accomplished
if(write_attempts <= 10) {
continue;
} else {
// Too many write attempts
syslog(LOG_ERR, "Failure during BIO_write, returning null String");
BIO_free_all(b64);
Signature.clear();
return Signature;
}
} else {
// If not a retry then it is an error
syslog(LOG_ERR, "Failure during BIO_write, returning null String");
BIO_free_all(b64);
Signature.clear();
return Signature;
}
}
// The write request succeeded in writing some Bytes
offset += bytes_written;
md_len -= bytes_written;
// If there is no more data to write, the request sending has been
// completed
if (md_len <= 0) {
break;
}
}
// Flush the data
ret = BIO_flush(b64);
if ( ret <= 0) {
syslog(LOG_ERR, "Failure during BIO_flush, returning null String");
BIO_free_all(b64);
Signature.clear();
return Signature;
}
BUF_MEM *bptr;
BIO_get_mem_ptr(b64, &bptr);
Signature.resize(bptr->length - 1);
memcpy(&Signature[0], bptr->data, bptr->length-1);
BIO_free_all(b64);
return Signature;
}
static size_t header_callback(void *data, size_t blockSize, size_t numBlocks, void *userPtr) {
headers_t* headers = reinterpret_cast<headers_t*>(userPtr);
string header(reinterpret_cast<char*>(data), blockSize * numBlocks);

View File

@ -42,7 +42,7 @@ std::string mount_prefix = "";
static std::string mountpoint;
std::string program_name;
static std::string AWSAccessKeyId;
static std::string AWSSecretAccessKey;
std::string AWSSecretAccessKey;
static mode_t root_mode = 0;
static std::string passwd_file = "";
static bool utility_mode = 0;
@ -75,8 +75,6 @@ static const char hexAlphabet[] = "0123456789ABCDEF";
// http headers
typedef std::map<std::string, std::string> headers_t;
static const EVP_MD* evp_md = EVP_sha1();
// fd -> flags
typedef std::map<int, int> s3fs_descriptors_t;
static s3fs_descriptors_t s3fs_descriptors;