diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-09-19 19:12:02 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-09-19 19:12:02 +0300 |
commit | df6e5f706ba36040ad7c60a66c1f30510f0dbba5 (patch) | |
tree | 2698289714be45e6f6b1ec5ac912e17d4d655c4a | |
parent | 1153970626892573e5966e135e8d81185f4ea53c (diff) | |
download | eclat-df6e5f706ba36040ad7c60a66c1f30510f0dbba5.tar.gz eclat-df6e5f706ba36040ad7c60a66c1f30510f0dbba5.tar.bz2 |
Implement query signature.
* lib/reqsign.c: New file
* lib/libeclat.h (eclat_query_signature): New proto.
* lib/Makefile.am: Add reqsign.c
-rw-r--r-- | lib/Makefile.am | 1 | ||||
-rw-r--r-- | lib/libeclat.h | 18 | ||||
-rw-r--r-- | lib/reqsign.c | 97 |
3 files changed, 116 insertions, 0 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 522a5bf..1162210 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -20,6 +20,7 @@ libeclat_a_SOURCES=\ base64.c\ hmac_sha1.c\ libeclat.h\ + reqsign.c\ sha1.c\ sha1.h\ urlencode.c diff --git a/lib/libeclat.h b/lib/libeclat.h index 0c6006e..1212dc4 100644 --- a/lib/libeclat.h +++ b/lib/libeclat.h @@ -27,3 +27,21 @@ void eclat_base64_encode(const unsigned char *input, size_t input_len, int eclat_base64_decode(const unsigned char *input, size_t input_len, unsigned char **output, size_t *output_len); + +struct ec2_param { + char *name; + char *value; +}; + +struct ec2_query { + int https; + char *endpoint; /* endpoint */ + char *uri; /* URI without parameters */ + char *verb; /* GET or POST */ + struct grecs_symtab *params; /* Query parameters */ +}; + +int eclat_query_signature(struct ec2_query *req, char *secret, + char **signature); + + diff --git a/lib/reqsign.c b/lib/reqsign.c new file mode 100644 index 0000000..bc65efe --- /dev/null +++ b/lib/reqsign.c @@ -0,0 +1,97 @@ +/* This file is part of Eclat. + Copyright (C) 2012 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 <config.h> +#include <string.h> +#include "libeclat.h" +#include "grecs.h" + +struct pname { + size_t i; + char **a; +}; + +static int +get_param_name(void *sym, void *data) +{ + struct grecs_syment *se = sym; + struct pname *pn = data; + pn->a[pn->i++] = se->name; + return 0; +} + +static int +compnames(const void *a, const void *b) +{ + char * const *ac = a; + char * const *bc = b; + return strcmp(*ac, *bc); +} + +int +eclat_query_signature(struct ec2_query *req, char *secret, + char **signature) +{ + char **pnames; + size_t i, n; + struct grecs_txtacc *acc; + struct pname pn; + char *str; + char digest[20]; + size_t siglen; + + acc = grecs_txtacc_create(); + + /* Collect and sort parameter names */ + n = grecs_symtab_count_entries(req->params); + pnames = grecs_calloc(n, sizeof(pnames[0])); + pn.i = 0; + pn.a = pnames; + grecs_symtab_enumerate(req->params, get_param_name, &pn); + qsort(pnames, n, sizeof(pnames[0]), compnames); + + grecs_txtacc_grow(acc, req->verb, strlen(req->verb)); + grecs_txtacc_grow_char(acc, '\n'); + grecs_txtacc_grow(acc, req->endpoint, strlen(req->endpoint)); + grecs_txtacc_grow_char(acc, '\n'); + grecs_txtacc_grow(acc, req->uri, strlen(req->uri)); + grecs_txtacc_grow_char(acc, '\n'); + + /* Append a canonicalized query string */ + for (i = 0; i < n; i++) { + struct ec2_param *p = + grecs_symtab_lookup_or_install(req->params, pnames[i], + NULL); + if (!p) + abort(); + if (i != 0) + grecs_txtacc_grow_char(acc, '&'); + grecs_txtacc_grow(acc, p->name, strlen(p->name)); + grecs_txtacc_grow_char(acc, '='); + if (p->value) + grecs_txtacc_grow(acc, p->value, strlen(p->value)); + } + grecs_txtacc_grow_char(acc, 0); + str = grecs_txtacc_finish(acc, 0); + + hmac_sha1(str, strlen(str), secret, strlen(secret), digest); + + eclat_base64_encode(digest, sizeof(digest), + (unsigned char**) signature, &siglen); + + grecs_txtacc_free(acc); + free(pnames); +} |