From 644b5c67f5e0f048eb0fd4ed208ef7dea3799c18 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 21 Oct 2013 13:33:01 +0000 Subject: [PATCH 1/3] Updated to 1.2, added support for IAM Temporary Credentials. --- debian/changelog | 6 + debian/source/format | 1 + src/Makefile | 6 +- src/jsonz.c | 357 +++++++++++++++++++++++++++++++++++++++++++ src/jsonz/jsonz.h | 27 ++++ src/jsonz/object.h | 59 +++++++ src/object.c | 311 +++++++++++++++++++++++++++++++++++++ src/s3.cc | 139 ++++++++++++++--- src/s3.h | 7 + src/s3_main.cc | 3 + 10 files changed, 892 insertions(+), 24 deletions(-) create mode 100644 debian/source/format create mode 100644 src/jsonz.c create mode 100644 src/jsonz/jsonz.h create mode 100644 src/jsonz/object.h create mode 100644 src/object.c diff --git a/debian/changelog b/debian/changelog index 0363cca..4e8b96e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +apt-transport-s3 (1.2) precise; urgency=low + + * Updated to use IAM temporary credentials + + -- Aurélien Guillaume Mon, 21 Oct 2013 09:58:00 +0000 + apt-transport-s3 (1.1.1ubuntu2) precise; urgency=low * Modified for company needs diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..89ae9db --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/src/Makefile b/src/Makefile index d57765b..c599602 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,11 +4,13 @@ default: s3 clean: rm -f *.o s3 -s3: s3_main.o s3.o connect.o - g++ -o s3 s3.o s3_main.o connect.o -lapt-pkg -lapt-inst -lssl -lcrypto +s3: s3_main.o s3.o connect.o jsonz.o object.o + g++ -g -o s3 s3.o s3_main.o connect.o jsonz.o object.o -lapt-pkg -lapt-inst -lssl -lcrypto -lcurl %.o: %.cc gcc -I /usr/include -I./ -g -c $< +%.o: %.c + gcc -I /usr/include -I./ -g -c $< install: s3 cp s3 /usr/lib/apt/methods/ diff --git a/src/jsonz.c b/src/jsonz.c new file mode 100644 index 0000000..dafd42d --- /dev/null +++ b/src/jsonz.c @@ -0,0 +1,357 @@ +/* + * jsonz.c + * libjsonz + * + * Created by Árpád Goretity on 29/12/2011. + * Licensed under a CreativeCommons Attribution 3.0 Unported License + */ + +#include +#include + +typedef struct jsonz_parser_t { + const char *str; +} jsonz_parser_t; + +static inline void skip_space(jsonz_parser_t *p) +{ + while (isspace(*p->str)) + p->str++; +} + +static long unescape_char(jsonz_parser_t *p) +{ + /* skip leading backslash '\' */ + switch (*++p->str) { + case '\\': p->str++; return '\\'; + case '/': p->str++; return '/'; + case '\'': p->str++; return '\''; + case '"': p->str++; return '\"'; + case 'a': p->str++; return '\a'; + case 'b': p->str++; return '\b'; + case 'f': p->str++; return '\f'; + case 'n': p->str++; return '\n'; + case 'r': p->str++; return '\r'; + case 't': p->str++; return '\t'; + case '0': p->str++; return '\0'; + case 'u': + p->str++; + if (isxdigit(p->str[0]) + && isxdigit(p->str[1]) + && isxdigit(p->str[2]) + && isxdigit(p->str[3])) { + char buf[5]; + memcpy(buf, p->str, 4); + buf[4] = 0; + p->str += 4; + return strtol(buf, NULL, 16); /* can't overflow */ + } + + /* invalid hex escape sequence */ + fprintf( + stderr, + "libjsonz: invalid escape sequence '\\u%c%c%c%c'\n", + p->str[0], + p->str[1], + p->str[2], + p->str[3] + ); + return -1; + default: + fprintf(stderr, "libjsonz: invalid escape sequence \\%c\n", *p->str); + return -1; + } +} + +static void *parse(jsonz_parser_t *p); + +static void *parse_num(jsonz_parser_t *p) +{ + int isfloat = 0; + + const char *s = p->str; + while (isdigit(*p->str)) + p->str++; + + if (*p->str == '.') { + isfloat = 1; + p->str++; + } + + while (isdigit(*p->str)) + p->str++; + + if (tolower(*p->str) == 'e') { + isfloat = 1; + p->str++; + + if (!isdigit(*p->str)) + return NULL; + + while (isdigit(*p->str)) + p->str++; + } + + char *end; + void *obj; + if (isfloat) { + double d = strtod(s, &end); + if (end != p->str) + return NULL; + + obj = jsonz_object_new(JSONZ_TYPE_FLOAT); + jsonz_number_set_float_value(obj, d); + } else { + long long n = strtoll(s, &end, 10); + if (end != p->str) + return NULL; + + obj = jsonz_object_new(JSONZ_TYPE_INT); + jsonz_number_set_int_value(obj, n); + } + + return obj; +} + +static void *parse_str(jsonz_parser_t *p) +{ + size_t sz = 0x20; + size_t n = 0; + char *buf = malloc(sz); + if (buf == NULL) + return NULL; + + /* skip '"' */ + p->str++; + + while (*p->str != '"') { + if (*p->str == 0) { + /* premature end of string */ + fprintf(stderr, "end of input before closing \" in string\n"); + free(buf); + return NULL; + } + + if (p->str[0] == '\\') { + long c = unescape_char(p); + if (c < 0) { + /* error unescaping the character */ + free(buf); + return NULL; + } + + if (c >> 8) { + buf[n++] = (c & 0xff00) >> 8; + } + + buf[n++] = c & 0xff; + } else { + buf[n++] = *p->str++; + } + + /* expand the buffer if necessary */ + if (n >= sz) { + sz <<= 1; + char *tmp = realloc(buf, sz); + if (tmp == NULL) + abort(); + + buf = tmp; + } + + + } + + buf[n] = 0; + + /* skip '"' */ + p->str++; + + void *obj = jsonz_object_new(JSONZ_TYPE_STRING); + jsonz_string_set_str_nocopy(obj, buf); + return obj; +} + +static void *parse_tru(jsonz_parser_t *p) +{ + if (memcmp(p->str, "true", 4) == 0) { + p->str += 4; + void *obj = jsonz_object_new(JSONZ_TYPE_BOOL); + jsonz_number_set_bool_value(obj, 1); + return obj; + } + + fprintf(stderr, "libjsonz: expected 'true'\n"); + return NULL; +} + +static void *parse_fal(jsonz_parser_t *p) +{ + if (memcmp(p->str, "false", 5) == 0) { + p->str += 5; + void *obj = jsonz_object_new(JSONZ_TYPE_BOOL); + jsonz_number_set_bool_value(obj, 0); + return obj; + } + + fprintf(stderr, "libjsonz: expected 'false'\n"); + return NULL; +} + +static void *parse_nul(jsonz_parser_t *p) +{ + if (memcmp(p->str, "null", 4) == 0) { + p->str += 4; + return jsonz_object_new(JSONZ_TYPE_NULL); + } + + fprintf(stderr, "libjsonz: expected 'null'\n"); + return NULL; +} + +static void *parse_arr(jsonz_parser_t *p) +{ + /* skip '[' */ + p->str++; + + skip_space(p); + if (*p->str == 0) { + fprintf(stderr, "libjsonz: unexpected end of input in array\n"); + return NULL; + } + + void *obj = jsonz_object_new(JSONZ_TYPE_ARRAY); + + while (*p->str != ']') { + void *elem = parse(p); + + if (elem == NULL) { + jsonz_object_free(obj); + return NULL; + } + + skip_space(p); + if (*p->str != ',' && *p->str != ']') { + fprintf(stderr, "libjsonz: expected ']' or ',' in array\n"); + jsonz_object_free(elem); + jsonz_object_free(obj); + return NULL; + } + + jsonz_array_add(obj, elem); + + /* skip ',' */ + if (*p->str == ',') + p->str++; + } + + /* skip ']' */ + p->str++; + return obj; +} + +static void *parse_dic(jsonz_parser_t *p) +{ + /* skip '{' */ + p->str++; + + skip_space(p); + if (*p->str == 0) { + fprintf(stderr, "libjsonz: unexpected end of input in dictionary\n"); + return NULL; + } + + void *obj = jsonz_object_new(JSONZ_TYPE_DICT); + + while (*p->str != '}') { + void *key = parse(p); + + if (key == NULL) { + jsonz_object_free(obj); + return NULL; + } + + if (jsonz_object_get_type(key) != JSONZ_TYPE_STRING) { + fprintf(stderr, "libjsonz: dictionary key must be a string\n"); + jsonz_object_free(key); + jsonz_object_free(obj); + return NULL; + } + + skip_space(p); + if (*p->str != ':') { + fprintf(stderr, "libjsonz: expected ':' after dictionary key\n"); + jsonz_object_free(key); + jsonz_object_free(obj); + return NULL; + } + + /* skip ':' */ + p->str++; + skip_space(p); + + void *elem = parse(p); + if (elem == NULL) { + fprintf(stderr, "libjsonz: expected value after key in dictionary\n"); + jsonz_object_free(key); + jsonz_object_free(elem); + jsonz_object_free(obj); + return NULL; + } + + skip_space(p); + if (*p->str != ',' && *p->str != '}') { + fprintf(stderr, "libjsonz: expected '}' or ',' in dictionary\n"); + jsonz_object_free(key); + jsonz_object_free(elem); + jsonz_object_free(obj); + return NULL; + } + + jsonz_dict_set(obj, jsonz_string_get_str(key), elem); + + skip_space(p); + + /* skip ',' */ + if (*p->str == ',') + p->str++; + } + + /* skip '}' */ + p->str++; + return obj; +} + +void *jsonz_parse(const char *str) +{ + jsonz_parser_t p = { str }; + void *obj = parse(&p); + return obj; +} + +/* a simple recursive descent parser */ +static void *parse(jsonz_parser_t *p) +{ + skip_space(p); + + switch (*p->str) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': return parse_num(p); + case '"': return parse_str(p); + case '[': return parse_arr(p); + case '{': return parse_dic(p); + case 't': return parse_tru(p); + case 'f': return parse_fal(p); + case 'n': return parse_nul(p); + default : return NULL; + } +} + diff --git a/src/jsonz/jsonz.h b/src/jsonz/jsonz.h new file mode 100644 index 0000000..daa1390 --- /dev/null +++ b/src/jsonz/jsonz.h @@ -0,0 +1,27 @@ +/* + * jsonz.h + * libjsonz + * + * Created by Árpád Goretity on 29/12/2011. + * Licensed under a CreativeCommons Attribution 3.0 Unported License + */ + +#include +#include +#include + +#ifndef JSONZ_JSONZ_H +#define JSONZ_JSONZ_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void *jsonz_parse(const char *str); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* JSONZ_JSONZ_H */ + diff --git a/src/jsonz/object.h b/src/jsonz/object.h new file mode 100644 index 0000000..36ca0cf --- /dev/null +++ b/src/jsonz/object.h @@ -0,0 +1,59 @@ +/* + * object.h + * libjsonz + * + * Created by Árpád Goretity on 29/12/2011. + * Licensed under a CreativeCommons Attribution 3.0 Unported License + */ + + +#ifndef JSONZ_OBJECT_H +#define JSONZ_OBJECT_H + +#include +#include + + +#define JSONZ_TYPE_NULL 0 +#define JSONZ_TYPE_BOOL 1 +#define JSONZ_TYPE_INT 2 +#define JSONZ_TYPE_FLOAT 3 +#define JSONZ_TYPE_STRING 4 +#define JSONZ_TYPE_ARRAY 5 +#define JSONZ_TYPE_DICT 6 + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void *jsonz_object_new(int type); +void jsonz_object_free(void *obj); +int jsonz_object_get_type(void *obj); + +int jsonz_number_get_bool_value(void *obj); +long long jsonz_number_get_int_value(void *obj); +double jsonz_number_get_float_value(void *obj); +void jsonz_number_set_bool_value(void *obj, int b); +void jsonz_number_set_int_value(void *obj, long long i); +void jsonz_number_set_float_value(void *obj, double d); + +const char *jsonz_string_get_str(void *obj); +void jsonz_string_set_str(void *obj, const char *str_new); +void jsonz_string_set_str_nocopy(void *obj, char *str_new); + +size_t jsonz_array_size(void *obj); +void *jsonz_array_get(void *obj, unsigned idx); +void jsonz_array_add(void *obj, void *elem); + +size_t jsonz_dict_size(void *obj); +const char *jsonz_dict_key(void *obj, unsigned index); +void *jsonz_dict_get(void *obj, const char *key); +/* returns previous element for the key or NULL if not yet present */ +void *jsonz_dict_set(void *obj, const char *key, void *elem); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* JSONZ_OBJECT_H */ + diff --git a/src/object.c b/src/object.c new file mode 100644 index 0000000..94e504b --- /dev/null +++ b/src/object.c @@ -0,0 +1,311 @@ +/* + * object.c + * libjsonz + * + * Created by Árpád Goretity on 29/12/2011. + * Licensed under a CreativeCommons Attribution 3.0 Unported License + */ + +#include +#include +#include + +typedef struct jsonz_object_t { + int type; +} jsonz_object_t; + +typedef struct jsonz_null_t { + jsonz_object_t base; +} jsonz_null_t; + +typedef struct jsonz_number_t { + jsonz_object_t base; + union { + double fltval; + long long intval; + } val; +} jsonz_number_t; + +typedef struct jsonz_string_t { + jsonz_object_t base; + char *str; +} jsonz_string_t; + +typedef struct jsonz_array_t { + jsonz_object_t base; + size_t size; + void **vals; +} jsonz_array_t; + +typedef struct jsonz_dict_t { + jsonz_object_t base; + size_t size; + char **keys; + void **vals; +} jsonz_dict_t; + +static void *chkmalloc(size_t sz) +{ + void *p = malloc(sz); + if (!p) + abort(); + + return p; +} + +void *jsonz_object_new(int type) +{ + jsonz_object_t *obj; + jsonz_number_t *num; + jsonz_string_t *str; + jsonz_array_t *arr; + jsonz_dict_t *dic; + void *o; + + switch (type) { + case JSONZ_TYPE_NULL: + o = chkmalloc(sizeof(jsonz_null_t)); + break; + case JSONZ_TYPE_BOOL: + case JSONZ_TYPE_INT: + o = chkmalloc(sizeof(jsonz_number_t)); + num = o; + num->val.intval = 0; + break; + case JSONZ_TYPE_FLOAT: + o = chkmalloc(sizeof(jsonz_number_t)); + num = o; + num->val.fltval = 0.0; + break; + case JSONZ_TYPE_STRING: + o = chkmalloc(sizeof(jsonz_string_t)); + str = o; + str->str = NULL; + break; + case JSONZ_TYPE_ARRAY: + o = chkmalloc(sizeof(jsonz_array_t)); + arr = o; + arr->size = 0; + arr->vals = NULL; + break; + case JSONZ_TYPE_DICT: + o = chkmalloc(sizeof(jsonz_dict_t)); + dic = o; + dic->size = 0; + dic->keys = NULL; + dic->vals = NULL; + break; + default: + return NULL; + } + + obj = o; + obj->type = type; + return obj; +} + +void jsonz_object_free(void *obj) +{ + jsonz_string_t *str = obj; + jsonz_array_t *arr = obj; + jsonz_dict_t *dic = obj; + jsonz_object_t *o = obj; + unsigned i; + + switch (o->type) { + case JSONZ_TYPE_STRING: + free(str->str); + break; + case JSONZ_TYPE_ARRAY: + for (i = 0; i < arr->size; i++) { + jsonz_object_free(arr->vals[i]); + } + break; + case JSONZ_TYPE_DICT: + for (i = 0; i < dic->size; i++) { + free(dic->keys[i]); + jsonz_object_free(dic->vals[i]); + } + break; + case JSONZ_TYPE_NULL: + case JSONZ_TYPE_BOOL: + case JSONZ_TYPE_INT: + case JSONZ_TYPE_FLOAT: + default: + break; + } + + free(obj); +} + +/* + * Querying object types + */ + +int jsonz_object_get_type(void *obj) +{ + jsonz_object_t *o = obj; + return o->type; +} + +/* + * Number and boolean functions + */ + +int jsonz_number_get_bool_value(void *obj) +{ + jsonz_number_t *num = obj; + return num->val.intval != 0; +} + +long long jsonz_number_get_int_value(void *obj) +{ + jsonz_number_t *num = obj; + return num->val.intval; +} + +double jsonz_number_get_float_value(void *obj) +{ + jsonz_number_t *num = obj; + return num->val.fltval; +} + +void jsonz_number_set_bool_value(void *obj, int b) +{ + jsonz_number_t *num = obj; + num->val.intval = !!b; +} + +void jsonz_number_set_int_value(void *obj, long long i) +{ + jsonz_number_t *num = obj; + num->val.intval = i; +} + +void jsonz_number_set_float_value(void *obj, double d) +{ + jsonz_number_t *num = obj; + num->val.fltval = d; +} + +/* + * String functions + */ + +const char *jsonz_string_get_str(void *obj) +{ + jsonz_string_t *str = obj; + return str->str; +} + +void jsonz_string_set_str(void *obj, const char *str_new) +{ + jsonz_string_t *str = obj; + free(str->str); + str->str = strdup(str_new); +} + +void jsonz_string_set_str_nocopy(void *obj, char *str_new) +{ + jsonz_string_t *str = obj; + free(str->str); + str->str = str_new; +} + +/* + * Array functions + */ + +size_t jsonz_array_size(void *obj) +{ + jsonz_array_t *arr = obj; + return arr->size; +} + +void *jsonz_array_get(void *obj, unsigned idx) +{ + jsonz_array_t *arr = obj; + return arr->vals[idx]; +} + +void jsonz_array_add(void *obj, void *elem) +{ + jsonz_array_t *arr = obj; + + /* + * make room for the new element + */ + void **v = realloc(arr->vals, (arr->size + 1) * sizeof(*v)); + if (!v) + abort(); + + arr->vals = v; + arr->vals[arr->size++] = elem; +} + + +/* + * Dictionary functions (a. k. a. Associative Arrays) + */ + +size_t jsonz_dict_size(void *obj) +{ + jsonz_dict_t *dic = obj; + return dic->size; +} + +const char *jsonz_dict_key(void *obj, unsigned index) +{ + + jsonz_dict_t *dic = obj; + return dic->keys[index]; +} + +void *jsonz_dict_get(void *obj, const char *key) +{ + jsonz_dict_t *dic = obj; + unsigned i; + for (i = 0; i < dic->size; i++) { + if (strcmp(dic->keys[i], key) == 0) + return dic->vals[i]; + } + + return NULL; +} + +void *jsonz_dict_set(void *obj, const char *key, void *elem) +{ + /* + * if the object already contains this key, we just + * exchange it with the new one + */ + jsonz_dict_t *dic = obj; + unsigned i; + for (i = 0; i < dic->size; i++) { + if (strcmp(dic->keys[i], key) == 0) { + void *prv = dic->vals[i]; + dic->vals[i] = elem; + return prv; + } + } + + /* + * if the key is not yet present, add it + */ + dic->size++; + char **k = realloc(dic->keys, dic->size * sizeof(*k)); + void **v = realloc(dic->vals, dic->size * sizeof(*v)); + if (k == NULL || v == NULL) + abort(); + + dic->keys = k; + dic->vals = v; + char *key_new = strdup(key); + if (!key_new) + abort(); + + dic->keys[dic->size - 1] = key_new; + dic->vals[dic->size - 1] = elem; + return NULL; +} + diff --git a/src/s3.cc b/src/s3.cc index 75d6a60..2b31ff2 100644 --- a/src/s3.cc +++ b/src/s3.cc @@ -63,6 +63,7 @@ #include #include +#include // Internet stuff #include @@ -71,6 +72,7 @@ #include "connect.h" #include "rfc2553emu.h" #include "s3.h" +#include "jsonz/jsonz.h" #define SLEN 1024 @@ -782,37 +784,46 @@ void HttpMethod::SendReq(FetchItem *Itm,CircleBuf &Out) string dateString((const char*)buffer); Req += "Date: " + dateString + "\r\n"; - string extractedPassword; - if (Uri.Password.empty() && NULL == getenv("AWS_SECRET_ACCESS_KEY")) { + string extractedPassword = s3TempSecretAccessKey; + if (!Uri.Password.empty()) + extractedPassword = Uri.Password; + if (!Uri.Password.empty() && Uri.Password.at(0) == '[') + extractedPassword = Uri.Password.substr(1,Uri.Password.size()-2); + if (getenv("AWS_SECRET_ACCESS_KEY")) + extractedPassword = getenv("AWS_SECRET_ACCESS_KEY"); + if (extractedPassword.empty()) + { cerr << "E: No AWS_SECRET_ACCESS_KEY set" << endl; exit(1); - } else if(Uri.Password.empty()) { - extractedPassword = getenv("AWS_SECRET_ACCESS_KEY"); - } else { - if(Uri.Password.at(0) == '['){ - extractedPassword = Uri.Password.substr(1,Uri.Password.size()-2); - }else{ - extractedPassword = Uri.Password; - } + } + + string user = s3TempAccessKeyId; + + if (!Uri.User.empty()) + user = Uri.User; + if (getenv("AWS_ACCESS_KEY_ID")) + user = getenv("AWS_ACCESS_KEY_ID"); + if (user.empty()) + { + cerr << "E: No AWS_ACCESS_KEY_ID set" << endl; + exit(1); } char headertext[SLEN], signature[SLEN]; - sprintf(headertext,"GET\n\n\n%s\n%s", dateString.c_str(), normalized_path.c_str()); + if (user == s3TempAccessKeyId) + sprintf(headertext,"GET\n\n\n%s\nx-amz-security-token:%s\n%s", dateString.c_str(), s3TempToken.c_str(), normalized_path.c_str()); + else + sprintf(headertext,"GET\n\n\n%s\n%s", dateString.c_str(), normalized_path.c_str()); doEncrypt(headertext, signature, extractedPassword.c_str()); string signatureString(signature); - string user; - if (Uri.User.empty() && NULL == getenv("AWS_ACCESS_KEY_ID")) { - cerr << "E: No AWS_ACCESS_KEY_ID set" << endl; - exit(1); - } else if (Uri.User.empty()) { - user = getenv("AWS_ACCESS_KEY_ID"); - } else { - user = Uri.User; - } - - //cerr << "user " << user << "\n"; + + +// cerr << "user " << user << "\n"; +// cerr << "access key " << extractedPassword << "\n"; Req += "Authorization: AWS " + user + ":" + signatureString + "\r\n"; + if (user == s3TempAccessKeyId) + Req += "X-Amz-Security-Token: " + s3TempToken + "\r\n"; Req += "User-Agent: Ubuntu APT-HTTP/1.3 ("VERSION")\r\n\r\n"; if (Debug == true) @@ -1167,6 +1178,88 @@ bool HttpMethod::Configuration(string Message) Debug = _config->FindB("Debug::Acquire::http",false); return true; } + +namespace { +static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) +{ + std::string buf = std::string(static_cast(ptr), size * nmemb); + std::stringstream *response = static_cast(stream); + response->write(buf.c_str(), (std::streamsize)buf.size()); + return size * nmemb; +} +} + +bool HttpMethod::GetURLWithHeaders(const std::string &url, const std::vector &headers, + std::stringstream &response, std::string &error) +{ + curl_slist *headerlist = NULL; + + std::vector::const_iterator it; + for (it = headers.begin(); it < headers.end(); it++) { + headerlist = curl_slist_append(headerlist, it->c_str()); + } + + CURL *curl = curl_easy_init(); + char ebuf[CURL_ERROR_SIZE]; + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, ebuf); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); + CURLcode res = curl_easy_perform(curl); + curl_easy_cleanup(curl); + curl_slist_free_all(headerlist); + + if (res != CURLE_OK) + error = ebuf; + else + error.clear(); + + return res == CURLE_OK; +} + + /*}}}*/ +// HttpMethod::GetS3IAMCreds /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void HttpMethod::GetS3IAMCreds() +{ + std::string error, url; + std::vector hdrs; + std::stringstream result; + + if (!GetURLWithHeaders("http://169.254.169.254/latest/meta-data/iam/security-credentials/", hdrs, result, error)) + return ; + + if (result.str().empty()) + return ; + + url = "http://169.254.169.254/latest/meta-data/iam/security-credentials/"; + url += s3TempRoleName = result.str(); + + result.str(""); + result.clear(); + + if (!GetURLWithHeaders(url, hdrs, result, error)) + return ; + + void *iam = jsonz_parse(result.str().c_str()); + if (!iam || jsonz_object_get_type(iam) != JSONZ_TYPE_DICT) + return ; + + void *obj; + obj = jsonz_dict_get(iam, "AccessKeyId"); + if (obj && jsonz_object_get_type(obj) == JSONZ_TYPE_STRING) + s3TempAccessKeyId = jsonz_string_get_str(obj); + obj = jsonz_dict_get(iam, "SecretAccessKey"); + if (obj && jsonz_object_get_type(obj) == JSONZ_TYPE_STRING) + s3TempSecretAccessKey = jsonz_string_get_str(obj); + obj = jsonz_dict_get(iam, "Token"); + if (obj && jsonz_object_get_type(obj) == JSONZ_TYPE_STRING) + s3TempToken = jsonz_string_get_str(obj); +} + /*}}}*/ // HttpMethod::Loop - Main loop /*{{{*/ // --------------------------------------------------------------------- @@ -1176,6 +1269,8 @@ int HttpMethod::Loop() signal(SIGTERM,SigTerm); signal(SIGINT,SigTerm); + GetS3IAMCreds(); + Server = 0; int FailCounter = 0; diff --git a/src/s3.h b/src/s3.h index 38af820..9d1a5cb 100644 --- a/src/s3.h +++ b/src/s3.h @@ -160,6 +160,13 @@ class HttpMethod : public pkgAcqMethod static time_t FailTime; static void SigTerm(int); + void GetS3IAMCreds(); + bool GetURLWithHeaders(const string &, const vector &, std::stringstream &, string &); + string s3TempRoleName; + string s3TempAccessKeyId; + string s3TempSecretAccessKey; + string s3TempToken; + protected: virtual bool Fetch(FetchItem *); diff --git a/src/s3_main.cc b/src/s3_main.cc index a331d8f..eb5792e 100644 --- a/src/s3_main.cc +++ b/src/s3_main.cc @@ -17,7 +17,9 @@ #include #include +#include +#include #include "connect.h" #include "rfc2553emu.h" #include "s3.h" @@ -31,6 +33,7 @@ int main() { setlocale(LC_ALL, ""); + curl_global_init(CURL_GLOBAL_ALL); HttpMethod Mth; return Mth.Loop(); } From 5ccf6e17a40851b788a431b7be7c4834d32a6a86 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 22 Oct 2013 09:10:39 +0000 Subject: [PATCH 2/3] Removed precise dependency on libapt-pkg4.12 --- debian/control | 2 +- debian/rules | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/debian/control b/debian/control index 9e6a3c1..ea00948 100644 --- a/debian/control +++ b/debian/control @@ -8,7 +8,7 @@ Build-Depends: debhelper (>= 5.0), libapt-pkg-dev (>= 0.7.23), cdbs, libcurl4-op Package: apt-transport-s3 Architecture: any -Depends: ${shlibs:Depends} +Depends: ${shlibs:Depends}, libapt-pkg4.12 Description: an APT transport for communicating with Amazon S3 This package contains the APT amazon s3 transport. It makes it possible to use diff --git a/debian/rules b/debian/rules index 89756c5..6cacd89 100755 --- a/debian/rules +++ b/debian/rules @@ -2,11 +2,12 @@ # vim: tabstop=4 softtabstop=4 noexpandtab fileencoding=utf-8 # Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 +export DH_VERBOSE=1 include /usr/share/cdbs/1/rules/debhelper.mk DEB_DIR=$(CURDIR)/debian/apt-transport-s3 +DEB_DH_SHLIBDEPS_ARGS=--dpkg-shlibdeps-params "-xlibapt-pkg4.12" #configure/apt-transport-s3:: # @echo "We don't really have a configure script" From daf8174df59825c873343f3209fb236d36c8fad0 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 22 Oct 2013 09:14:20 +0000 Subject: [PATCH 3/3] Version bump --- debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index 4e8b96e..0408d5a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +apt-transport-s3 (1.2ubuntu1) precise; urgency=low + + * Loosening dependency on libapt-pkg4.12 + + -- Aurélien Guillaume Tue, 22 Oct 2013 09:12:47 +0000 + apt-transport-s3 (1.2) precise; urgency=low * Updated to use IAM temporary credentials