aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2015-01-19 11:26:48 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2015-01-19 11:35:21 +0200
commit4d1258de786a83888d123f4e8f791f1ad6ecf605 (patch)
treee172edcda699af4b7db72f42e30f4399866b339b /lib
parent0766417065bfec9747bf0f41f9b68c27e378f817 (diff)
downloadeclat-4d1258de786a83888d123f4e8f791f1ad6ecf605.tar.gz
eclat-4d1258de786a83888d123f4e8f791f1ad6ecf605.tar.bz2
Initial support for IAM
* NEWS: Update. * doc/eclat.1man: Update. * lib/.gitignore: Update. * lib/Makefile.am (libeclat_a_SOURCES): Add new files. * lib/json.h: New file. * lib/jsongrm.y: New file. * lib/jsonlex.l: New file. * lib/yytrans: New file. * lib/libeclat.h (ec2_query) <token>: New member (eclat_query_create): Change signature. * lib/qcreat.c (eclat_query_create): Take security token as 5th argument. * lib/reqsign.c (querysign2): Add security token. * src/cmdline.opt: Update copyright years * src/ec2map.c (ec2_map_get): Pass security token to eclat_query_create. * src/eclat.c (security_token): New variable. (eclat_do_command): Pass security token to eclat_query_create. (main): Get authentication credentials from the instance store, if not found in the access file. * src/eclat.h (security_token): New extern. (eclat_get_instance_creds): New proto. * src/util.c (eclat_get_instance_zone): Use json parser. (eclat_get_instance_creds): New function. * tests/Makefile.am (noinst_PROGRAMS): add tjson * tests/tjson.c: New file.
Diffstat (limited to 'lib')
-rw-r--r--lib/.gitignore4
-rw-r--r--lib/Makefile.am10
-rw-r--r--lib/json.h66
-rw-r--r--lib/jsongrm.y316
-rw-r--r--lib/jsonlex.l183
-rw-r--r--lib/libeclat.h3
-rw-r--r--lib/qcreat.c4
-rw-r--r--lib/reqsign.c2
-rw-r--r--lib/yytrans4
9 files changed, 590 insertions, 2 deletions
diff --git a/lib/.gitignore b/lib/.gitignore
index e0d9b22..e96121b 100644
--- a/lib/.gitignore
+++ b/lib/.gitignore
@@ -2,3 +2,7 @@ forlangrm.c
forlangrm.h
forlangrm.output
forlanlex.c
+jsongrm.c
+jsongrm.h
+jsongrm.output
+jsonlex.c
diff --git a/lib/Makefile.am b/lib/Makefile.am
index f3a9d42..428de49 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -42,6 +42,10 @@ libeclat_a_SOURCES=\
forlangrm.h\
forlangrm.y\
forlanlex.l\
+ json.h\
+ jsongrm.h\
+ jsongrm.y\
+ jsonlex.l\
getans.c\
getyn.c\
hmac_sha1.c\
@@ -68,8 +72,14 @@ AM_CPPFLAGS = -I$(top_srcdir)/grecs/src/ $(CURL_CFLAGS)
forlanlex.c: forlangrm.h
forlangrm.c forlangrm.h: forlangrm.y
+jsonlex.c: jsongrm.h
+jsongrm.c jsongrm.h: jsongrm.y
+
AM_YFLAGS=-tdv
AM_LFLAGS=-dp
+LEXCOMPILE = $(top_srcdir)/@GRECS_SUBDIR@/build-aux/yyrename '$(LEX) $(LFLAGS) $(AM_LFLAGS)'
+YACCCOMPILE = $(top_srcdir)/@GRECS_SUBDIR@/build-aux/yyrename '$(YACC) $(YFLAGS) $(AM_YFLAGS)'
+
diff --git a/lib/json.h b/lib/json.h
new file mode 100644
index 0000000..36ca243
--- /dev/null
+++ b/lib/json.h
@@ -0,0 +1,66 @@
+/* This file is part of Eclat.
+ Copyright (C) 2012-2015 Sergey Poznyakoff.
+
+ Eclat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ Eclat is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <grecs.h>
+
+enum json_object_type
+{
+ json_null,
+ json_bool,
+ json_number,
+ json_string,
+ json_arr,
+ json_obj
+};
+
+struct json_object;
+struct json_array {
+ size_t oc;
+ struct json_object **ov;
+};
+
+struct json_object {
+ enum json_object_type type;
+ union {
+ int b; /* json_bool */
+ double n; /* json_number */
+ char *s; /* json_string */
+ struct json_array *a; /* json_arr */
+ struct grecs_symtab *o; /* json_o */
+ } v;
+};
+
+struct json_pair {
+ char *k;
+ struct json_object *v;
+};
+
+extern char const *json_err_diag;
+extern char const *json_err_ptr;
+extern struct json_object *json_return_obj;
+
+void jsonlex_setup(char const *s, size_t l);
+void jsonlex_diag(const char *s, size_t off);
+struct json_object *json_object_create(int type);
+struct grecs_symtab *json_assoc_create(void);
+void json_object_free(struct json_object *obj);
+
+struct json_object *json_parse_string(char const *input, size_t len);
+
+struct json_object *json_object_lookup(struct json_object *obj,
+ const char *ident);
+
+
diff --git a/lib/jsongrm.y b/lib/jsongrm.y
new file mode 100644
index 0000000..398d2e7
--- /dev/null
+++ b/lib/jsongrm.y
@@ -0,0 +1,316 @@
+%{
+/* This file is part of Eclat.
+ Copyright (C) 2012-2015 Sergey Poznyakoff.
+
+ Eclat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ Eclat is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "libeclat.h"
+#include <string.h>
+#include "jsongrm.h"
+#include "json.h"
+
+struct json_object *json_return_obj;
+
+static int yyerror(char const *s);
+
+static struct json_pair *
+pairdup(struct json_pair *in)
+{
+ struct json_pair *out = grecs_malloc(sizeof(*out));
+ out->k = in->k;
+ out->v = in->v;
+ return out;
+}
+
+static void
+pairfree(void *ptr)
+{
+ struct json_pair *p = ptr;
+ free(p->k);
+ json_object_free(p->v);
+ free(p);
+}
+
+static void
+objfree(void *ptr)
+{
+ struct json_object *o = ptr;
+ json_object_free(o);
+}
+
+%}
+%token <n> T_NUMBER
+%token <s> T_STRING
+%token <b> T_BOOL
+%token T_NULL T_ERR
+
+%type <a> array
+%type <list> objects objlist pairs pairlist
+%type <p> pair
+%type <obj> object
+%type <o> assoc
+
+%union {
+ int b;
+ double n;
+ char *s;
+ struct json_array *a;
+ struct grecs_symtab *o;
+ struct json_object *obj;
+ struct grecs_list *list;
+ struct json_pair *p;
+}
+%%
+
+input : object
+ {
+ json_return_obj = $1;
+ }
+ ;
+
+object : T_NUMBER
+ {
+ $$ = json_object_create(json_number);
+ $$->v.n = $1;
+ }
+ | T_STRING
+ {
+ $$ = json_object_create(json_string);
+ $$->v.s = $1;
+ }
+ | T_BOOL
+ {
+ $$ = json_object_create(json_bool);
+ $$->v.b = $1;
+ }
+ | T_NULL
+ {
+ $$ = json_object_create(json_null);
+ }
+ | array
+ {
+ $$ = json_object_create(json_arr);
+ $$->v.a = $1;
+ }
+ | assoc
+ {
+ $$ = json_object_create(json_obj);
+ $$->v.o = $1;
+ }
+ ;
+
+array : '[' objects ']'
+ {
+ struct json_array *a = grecs_malloc(sizeof(*a));
+ if (!$2) {
+ a->oc = 0;
+ a->ov = NULL;
+ } else {
+ size_t i;
+ struct grecs_list_entry *ep;
+ a->oc = $2->count;
+ a->ov = grecs_calloc(a->oc, sizeof(a->ov));
+ for (i = 0, ep = $2->head; ep; i++, ep = ep->next) {
+ struct json_object *p = ep->data;
+ a->ov[i] = p;
+ }
+ }
+ $$ = a;
+ }
+ ;
+
+objects : /* empty */
+ {
+ $$ = NULL;
+ }
+ | objlist
+ ;
+
+objlist : object
+ {
+ $$ = grecs_list_create();
+ $$->free_entry = objfree;
+ grecs_list_append($$, $1);
+ }
+ | objlist ',' object
+ {
+ grecs_list_append($1, $3);
+ }
+ ;
+
+assoc : '{' pairs '}'
+ {
+ struct grecs_symtab *s;
+
+ s = json_assoc_create();
+ if ($2) {
+ struct grecs_list_entry *ep;
+ for (ep = $2->head; ep; ep = ep->next) {
+ struct json_pair *p = ep->data;
+ int install = 1;
+ grecs_symtab_lookup_or_install(s, p, &install);
+ if (install) {
+ p->k = NULL;
+ p->v = NULL;
+ }
+ }
+ grecs_list_free($2);
+ }
+ $$ = s;
+ }
+ ;
+
+pairs : /* empty */
+ {
+ $$ = NULL;
+ }
+ | pairlist
+ ;
+
+pairlist: pair
+ {
+ $$ = grecs_list_create();
+ $$->free_entry = pairfree;
+ grecs_list_append($$, $1);
+ }
+ | pairlist ',' pair
+ {
+ grecs_list_append($1, $3);
+ }
+ ;
+
+pair : T_STRING ':' object
+ {
+ struct json_pair *p = grecs_malloc(sizeof(*p));
+ p->k = $1;
+ p->v = $3;
+ $$ = p;
+ }
+ ;
+%%
+
+static int
+yyerror(char const *s)
+{
+ jsonlex_diag(s, 0);
+ return 0;
+}
+
+struct json_object *
+json_object_create(int type)
+{
+ struct json_object *obj = grecs_zalloc(sizeof(*obj));
+ obj->type = type;
+ return obj;
+}
+
+void
+json_object_free(struct json_object *obj)
+{
+ size_t i;
+
+ if (!obj)
+ return;
+
+ switch (obj->type) {
+ case json_bool:
+ case json_number:
+ break;
+ case json_string:
+ free(obj->v.s);
+ break;
+ case json_arr:
+ for (i = 0; i < obj->v.a->oc; i++)
+ json_object_free(obj->v.a->ov[i]);
+ free(obj->v.a);
+ break;
+ case json_obj:
+ grecs_symtab_free(obj->v.o);
+ }
+ free(obj);
+}
+
+static unsigned
+json_st_hash(void *data, unsigned long n_buckets)
+{
+ struct json_pair *p = data;
+ return grecs_hash_string(p->k, n_buckets);
+}
+
+static int
+json_st_cmp(const void *a, const void *b)
+{
+ struct json_pair const *pa = a;
+ struct json_pair const *pb = b;
+ return strcmp(pa->k, pb->k);
+}
+
+static int
+json_st_copy(void *a, void *b)
+{
+ struct json_pair *pa = a;
+ struct json_pair *pb = b;
+ memcpy(pa, pb, sizeof(*pa));
+ return 0;
+}
+
+static void
+json_st_free(void *ptr)
+{
+ struct json_pair *p = ptr;
+// printf("FREE %s\n", p->k);
+ free(p->k);
+ json_object_free(p->v);
+ free(p);
+}
+
+struct grecs_symtab *
+json_assoc_create()
+{
+ return grecs_symtab_create(sizeof(struct json_pair),
+ json_st_hash,
+ json_st_cmp,
+ json_st_copy,
+ NULL,
+ json_st_free);
+}
+
+struct json_object *
+json_parse_string(char const *input, size_t len)
+{
+ jsonlex_setup(input, len);
+ if (yyparse()) {
+ /* FIXME: error recovery */
+ return NULL;
+ }
+ return json_return_obj;
+}
+
+struct json_object *
+json_object_lookup(struct json_object *obj, const char *ident)
+{
+ struct json_pair key, *p;
+ if (!obj || obj->type != json_obj)
+ return NULL;
+ key.k = ident;
+ p = grecs_symtab_lookup_or_install(obj->v.o, &key, NULL);
+ if (!p)
+ return NULL;
+ return p->v;
+}
+
+
+
+
+
diff --git a/lib/jsonlex.l b/lib/jsonlex.l
new file mode 100644
index 0000000..322b05d
--- /dev/null
+++ b/lib/jsonlex.l
@@ -0,0 +1,183 @@
+%{
+/* This file is part of Eclat.
+ Copyright (C) 2012-2015 Sergey Poznyakoff.
+
+ Eclat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ Eclat is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Eclat. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "libeclat.h"
+#include "jsongrm.h"
+#include "json.h"
+
+static char const *input_ptr;
+static size_t input_size;
+
+char const *json_err_diag;
+char const *json_err_ptr;
+
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ do { \
+ size_t n = (max_size > input_size) ? input_size : max_size; \
+ if (n) { \
+ memcpy(buf, input_ptr, n); \
+ input_ptr += n; \
+ input_size -= n; \
+ } \
+ result = n; \
+ } while(0)
+
+void
+jsonlex_setup(char const *s, size_t l)
+{
+ input_ptr = s;
+ input_size = l;
+ json_err_diag = NULL;
+ json_err_ptr = NULL;
+ yy_flex_debug = 0;
+}
+
+void
+jsonlex_diag(const char *s, size_t off)
+{
+ if (!json_err_diag) {
+ json_err_diag = s;
+ json_err_ptr = input_ptr - off;
+ }
+}
+
+static int
+utf8_wctomb(char *u)
+{
+ unsigned int wc = strtoul(u, NULL, 16);
+ int count;
+ char r[6];
+
+ if (wc < 0x80)
+ count = 1;
+ else if (wc < 0x800)
+ count = 2;
+ else if (wc < 0x10000)
+ count = 3;
+ else if (wc < 0x200000)
+ count = 4;
+ else if (wc < 0x4000000)
+ count = 5;
+ else if (wc <= 0x7fffffff)
+ count = 6;
+ else
+ return -1;
+
+ switch (count) {
+ /* Note: code falls through cases! */
+ case 6:
+ r[5] = 0x80 | (wc & 0x3f);
+ wc = wc >> 6;
+ wc |= 0x4000000;
+ case 5:
+ r[4] = 0x80 | (wc & 0x3f);
+ wc = wc >> 6;
+ wc |= 0x200000;
+ case 4:
+ r[3] = 0x80 | (wc & 0x3f);
+ wc = wc >> 6;
+ wc |= 0x10000;
+ case 3:
+ r[2] = 0x80 | (wc & 0x3f);
+ wc = wc >> 6;
+ wc |= 0x800;
+ case 2:
+ r[1] = 0x80 | (wc & 0x3f);
+ wc = wc >> 6;
+ wc |= 0xc0;
+ case 1:
+ r[0] = wc;
+ }
+ grecs_line_acc_grow(r, count);
+ return count;
+}
+
+static int
+unescape(int c, int *o)
+{
+ static char transtab[] = "\\\\\"\"//b\bf\fn\nr\rt\t";
+ char *p;
+
+ for (p = transtab; *p; p += 2) {
+ if (*p == c) {
+ *o = p[1];
+ return 0;
+ }
+ }
+ return -1;
+}
+
+#define YY_SKIP_YYWRAP 1
+static int
+yywrap()
+{
+ return 1;
+}
+%}
+D [0-9]
+X [0-9a-fA-F]
+%x STR
+%%
+"-"?{D}{D}*(.{D}{D}*)?([eE][-+]?{D}{D}*)? {
+ yylval.n = strtod(yytext, NULL);
+ return T_NUMBER;
+ }
+\"[^\\\"]*\" { grecs_line_begin();
+ grecs_line_add(yytext + 1, yyleng - 2);
+ yylval.s = grecs_line_finish();
+ return T_STRING; }
+\"[^\\\"]*\\{X}{4} { BEGIN(STR);
+ grecs_line_begin();
+ grecs_line_add(yytext + 1, yyleng - 5);
+ utf8_wctomb(yytext + yyleng - 4);
+ }
+\"[^\\\"]*\\. { int c;
+ BEGIN(STR);
+ grecs_line_begin();
+ grecs_line_acc_grow(yytext + 1, yyleng - 2);
+ if (unescape(yytext[yyleng - 1], &c)) {
+ jsonlex_diag("invalid UTF-8 codepoint", 5);
+ return T_ERR;
+ }
+ grecs_line_acc_grow_char(c);
+ }
+<STR>[^\\\"]*\" { BEGIN(INITIAL);
+ if (yyleng > 1)
+ grecs_line_acc_grow(yytext, yyleng - 1);
+ yylval.s = grecs_line_finish();
+ return T_STRING; }
+<STR>[^\\\"]*\\{X}{4} {
+ grecs_line_add(yytext, yyleng - 5);
+ utf8_wctomb(yytext + yyleng - 4);
+}
+<STR>[^\\\"]*\\. {
+ int c;
+ grecs_line_acc_grow(yytext, yyleng - 2);
+ if (unescape(yytext[yyleng - 1], &c)) {
+ jsonlex_diag("invalid UTF-8 codepoint", 5);
+ return T_ERR;
+ }
+ grecs_line_acc_grow_char(c); }
+
+null { return T_NULL; }
+true { yylval.b = 1; return T_BOOL; }
+false { yylval.b = 0; return T_BOOL; }
+"{"|"}"|"["|"]"|":"|"," return yytext[0];
+[ \t\n]* ;
+. { jsonlex_diag("bogus character", 0);
+ return T_ERR; }
diff --git a/lib/libeclat.h b/lib/libeclat.h
index b7dc189..2265a7b 100644
--- a/lib/libeclat.h
+++ b/lib/libeclat.h
@@ -86,12 +86,13 @@ struct ec2_query {
struct grecs_list *headers; /* Query headers */
char *region;
char *access_key;
+ char *token;
unsigned long ttl; /* Time-to-live in seconds */
};
struct ec2_query *eclat_query_create(int flags, const char *endpoint,
const char *uri, char const *region,
- char const *access_key);
+ char const *access_key, char const *token);
void eclat_query_free(struct ec2_query *);
void eclat_query_add_param(struct ec2_query *q, const char *name,
const char *value);
diff --git a/lib/qcreat.c b/lib/qcreat.c
index 32471a0..c2898a5 100644
--- a/lib/qcreat.c
+++ b/lib/qcreat.c
@@ -29,7 +29,8 @@ ec2_param_free(void *ptr)
struct ec2_query *
eclat_query_create(int flags, const char *endpoint, const char *uri,
- char const *region, char const *access_key)
+ char const *region, char const *access_key,
+ char const *token)
{
struct ec2_query *q = grecs_zalloc(sizeof(*q));
q->flags = flags;
@@ -45,5 +46,6 @@ eclat_query_create(int flags, const char *endpoint, const char *uri,
q->ttl = 5;
q->region = grecs_strdup(region ? region : "us-east-1");
q->access_key = grecs_strdup(access_key);
+ q->token = token ? grecs_strdup(token) : NULL;
return q;
}
diff --git a/lib/reqsign.c b/lib/reqsign.c
index 397f6c8..4250907 100644
--- a/lib/reqsign.c
+++ b/lib/reqsign.c
@@ -64,6 +64,8 @@ querysign2(struct ec2_query *req, char *secret)
eclat_query_add_param(req, "AWSAccessKeyId", req->access_key);
eclat_query_add_param(req, "SignatureMethod", "HmacSHA256");
eclat_query_add_param(req, "SignatureVersion", "2");
+ if (req->token)
+ eclat_query_add_param(req, "SecurityToken", req->token);
time(&t);
strftime(tsbuf, sizeof(tsbuf), "%Y-%m-%dT%H:%M:%SZ", gmtime(&t));
diff --git a/lib/yytrans b/lib/yytrans
new file mode 100644
index 0000000..9e5979c
--- /dev/null
+++ b/lib/yytrans
@@ -0,0 +1,4 @@
+forlangrm forlan_yy_
+forlanlex forlan_yy_
+jsongrm json_yy_
+jsonlex json_yy_

Return to:

Send suggestions and report system problems to the System administrator.