Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 142 lines (120 sloc) 2.99 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
#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;
}
Something went wrong with that request. Please try again.