Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
142 lines (120 sloc) 2.92 KB
#include "openssl/hmac.h"
#include "postgres.h"
#include "lib/stringinfo.h"
#include "connutil.h"
static char *sign_by_secretkey(char *input, char *secretkey);
static int b64_encode(const uint8 *src, unsigned len, uint8 *dst);
/*
* Constructs GMT-style string
*/
char *
httpdate(time_t *timer)
{
char *datestring;
time_t t;
struct tm *gt;
t = time(timer);
gt = gmtime(&t);
datestring = (char *) palloc0(256 * sizeof(char));
strftime(datestring, 256 * sizeof(char), "%a, %d %b %Y %H:%M:%S +0000", gt);
return datestring;
}
/*
* Construct signed string for the Authorization header,
* following the Amazon S3 REST API spec.
*/
char *
s3_signature(char *method, char *datestring,
char *bucket, char *file, char *secretkey)
{
size_t rs_size;
char *resource;
StringInfoData buf;
rs_size = strlen(bucket) + strlen(file) + 3; /* 3 = '/' + '/' + '\0' */
resource = (char *) palloc0(rs_size);
snprintf(resource, rs_size, "/%s/%s", bucket, file);
initStringInfo(&buf);
/*
* StringToSign = HTTP-Verb + "\n" +
* Content-MD5 + "\n" +
* Content-Type + "\n" +
* Date + "\n" +
* CanonicalizedAmzHeaders +
* CanonicalizedResource;
*/
appendStringInfo(&buf, "%s\n", method);
appendStringInfo(&buf, "\n");
appendStringInfo(&buf, "\n");
appendStringInfo(&buf, "%s\n", datestring);
// appendStringInfo(&buf, "");
appendStringInfo(&buf, "%s", resource);
//elog(INFO, "StringToSign:%s", buf.data);
return sign_by_secretkey(buf.data, secretkey);
}
static char *
sign_by_secretkey(char *input, char *secretkey)
{
HMAC_CTX ctx;
/* sha1 has to be 30 charcters */
char result[256];
unsigned int len;
/* base64 may enlarge the size up to double */
char b64_result[256];
int b64_len;
HMAC_CTX_init(&ctx);
HMAC_Init(&ctx, secretkey, strlen(secretkey), EVP_sha1());
HMAC_Update(&ctx, (unsigned char *) input, strlen(input));
HMAC_Final(&ctx, (unsigned char *) result, &len);
HMAC_CTX_cleanup(&ctx);
b64_len = b64_encode((unsigned char *) result, len, (unsigned char *) b64_result);
b64_result[b64_len] = '\0';
return pstrdup(b64_result);
}
/*
* BASE64 - duplicated :(
*/
static int
b64_encode(const uint8 *src, unsigned len, uint8 *dst)
{
static const unsigned char _base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
uint8 *p,
*lend = dst + 76;
const uint8 *s,
*end = src + len;
int pos = 2;
unsigned long buf = 0;
s = src;
p = dst;
while (s < end)
{
buf |= *s << (pos << 3);
pos--;
s++;
/*
* write it out
*/
if (pos < 0)
{
*p++ = _base64[(buf >> 18) & 0x3f];
*p++ = _base64[(buf >> 12) & 0x3f];
*p++ = _base64[(buf >> 6) & 0x3f];
*p++ = _base64[buf & 0x3f];
pos = 2;
buf = 0;
}
if (p >= lend)
{
*p++ = '\n';
lend = p + 76;
}
}
if (pos != 2)
{
*p++ = _base64[(buf >> 18) & 0x3f];
*p++ = _base64[(buf >> 12) & 0x3f];
*p++ = (pos == 0) ? _base64[(buf >> 6) & 0x3f] : '=';
*p++ = '=';
}
return p - dst;
}