aeolus community release 0.4.0 "freeze"
by steve linabery
Hi aeolus community,
As of this writing, the aeolus conductor repo has a branch called 0.4.x whose tip is at 16fdbbd589e1d4030ac090d195fce12b9a5992e2
Please continue to commit to master as needed, but I need committers to tell me ASAP if they're committing stuff that needs to be cherry-picked over to the 0.4.x branch.
Plan is to cut 0.4.0 community release by EOD.
Thanks!
Steve|eggs
12 years, 6 months
BZ 718122 - Human-readable error helper
by Matt Wagner
This grew out of https://bugzilla.redhat.com/show_bug.cgi?id=718122 and the desire to show a more friendly message than the text of an exception we were given. This solution assumes that we're going to want to make use of this type of thing elsewhere down the road; as a stand-alone it's perhaps a little over-engineered.
This permits us to take an exception that is raised along the chain ("Connection refused - connect(2)"), pass in an optional context hint, and get back an internationalization-friendly message that makes sense to a human -- "Please make sure Deltacloud is running."
-- Matt
12 years, 6 months
[PATCH aeolus 1/2] Added Status check for imports
by Martyn Taylor
From: Martyn Taylor <mtaylor(a)redhat.com>
---
src/app/views/api/images/_factory_image.xml.haml | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/app/views/api/images/_factory_image.xml.haml b/src/app/views/api/images/_factory_image.xml.haml
index 09d2263..b930577 100644
--- a/src/app/views/api/images/_factory_image.xml.haml
+++ b/src/app/views/api/images/_factory_image.xml.haml
@@ -4,4 +4,4 @@
%target_images
- image.build.target_images.each do |target_image|
%target_image{:id => target_image.id, :href => api_target_image_url(target_image.id)}
- %status=Aeolus::Image::Factory::TargetImage.status(target_image.id)
\ No newline at end of file
+ %status=(Aeolus::Image::Factory::TargetImage.status(target_image.id) || "COMPLETE")
--
1.7.6.2
12 years, 6 months
[PATCH aeolus-image-rubygem] Added catch for http500 from factory
by Martyn Taylor
From: Martyn Taylor <mtaylor(a)redhat.com>
---
lib/aeolus_image/model/factory/provider_image.rb | 7 ++++++-
lib/aeolus_image/model/factory/target_image.rb | 7 ++++++-
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/lib/aeolus_image/model/factory/provider_image.rb b/lib/aeolus_image/model/factory/provider_image.rb
index 22db7d7..98b24dc 100644
--- a/lib/aeolus_image/model/factory/provider_image.rb
+++ b/lib/aeolus_image/model/factory/provider_image.rb
@@ -3,7 +3,12 @@ module Aeolus
module Factory
class ProviderImage < Base
def self.status(id)
- Aeolus::Image::Factory::Builder.find(id).status
+ begin
+ Aeolus::Image::Factory::Builder.find(id).status
+ # TODO Factory should throw a 404 here, this is to get round it
+ rescue
+ nil
+ end
end
end
end
diff --git a/lib/aeolus_image/model/factory/target_image.rb b/lib/aeolus_image/model/factory/target_image.rb
index 4c87006..d46237b 100644
--- a/lib/aeolus_image/model/factory/target_image.rb
+++ b/lib/aeolus_image/model/factory/target_image.rb
@@ -3,7 +3,12 @@ module Aeolus
module Factory
class TargetImage < Base
def self.status(id)
- Aeolus::Image::Factory::Builder.find(id).status
+ begin
+ Aeolus::Image::Factory::Builder.find(id).status
+ # TODO Factory should throw a 404 here, this is to get round it
+ rescue
+ nil
+ end
end
end
end
--
1.7.6.2
12 years, 6 months
[PATCH conductor] Implement User card automatic filling with the form information
by jzigmund@redhat.com
From: Jozef Zigmund <jzigmund(a)redhat.com>
---
src/app/stylesheets/custom.scss | 11 +++++++++++
src/app/views/users/_form.haml | 26 ++++++++++++++++++++++----
src/app/views/users/edit.haml | 7 ++++---
src/app/views/users/new.haml | 7 ++++---
4 files changed, 41 insertions(+), 10 deletions(-)
diff --git a/src/app/stylesheets/custom.scss b/src/app/stylesheets/custom.scss
index d019798..967137b 100644
--- a/src/app/stylesheets/custom.scss
+++ b/src/app/stylesheets/custom.scss
@@ -47,3 +47,14 @@
ul.deployment-array.small li.deployment {
height: 90px;
}
+
+div#user_card header.user-card-header h2#first_name {
+ color: white;
+ padding: 15px 10px 10px 60px;
+ background: transparent url('../../images/user_card_icon.png') no-repeat 12px 10px;
+}
+
+div#user_card header.user-card-header h2#first_name + h2#last_name {
+ padding: 0px;
+ background: transparent;
+}
\ No newline at end of file
diff --git a/src/app/views/users/_form.haml b/src/app/views/users/_form.haml
index 43f49f8..ca43636 100644
--- a/src/app/views/users/_form.haml
+++ b/src/app/views/users/_form.haml
@@ -4,17 +4,17 @@
%fieldset
%p
= form.label :first_name, t(:first_name)
- = form.text_field :first_name
+ = form.text_field :first_name, :class =>"check_change"
%p
= form.label :last_name, t(:last_name)
- = form.text_field :last_name
+ = form.text_field :last_name, :class =>"check_change"
%p
= form.label :email, t(:email)
- = form.text_field :email
+ = form.text_field :email, :class =>"check_change"
%fieldset
%p
= form.label :login, t(:choose_name)
- = form.text_field :login, :class => "em"
+ = form.text_field :login, :class => "em check_change"
%p
= form.label :password, form.object.new_record? ? t(:choose_password) : t(:change_password)
= form.password_field :password
@@ -48,3 +48,21 @@
%fieldset.options
= form.submit "Save User", :class => "submit button pill"
+
+:javascript
+ $('.check_change').change(function(){
+ switch(this.id){
+ case 'user_last_name':
+ $('h2#last_name').text(this.value);
+ break;
+ case 'user_first_name':
+ $('h2#first_name').text(this.value);
+ break;
+ case 'user_email':
+ $('dd#email').text(this.value);
+ break;
+ case 'user_login':
+ $('dd#login').text(this.value);
+ break;
+ }
+ });
diff --git a/src/app/views/users/edit.haml b/src/app/views/users/edit.haml
index ddbb891..aebcfd7 100644
--- a/src/app/views/users/edit.haml
+++ b/src/app/views/users/edit.haml
@@ -12,12 +12,13 @@
.content
#user_card.user_form_card
%header.user-card-header
- %h2= @user.name
+ %h2#first_name= @user.first_name
+ %h2#last_name= @user.last_name
.user-card-content
%dl
%dt E-mail Address
- %dd= @user.email
+ %dd#email= @user.email
%dt Username
- %dd= @user.login
+ %dd#login= @user.login
= form_for @user, :url => user_path(@user), :html => { :method => :put, :class => 'generic' } do |f|
= render :partial => "form", :locals => { :form => f, :cancel_path => users_path }
diff --git a/src/app/views/users/new.haml b/src/app/views/users/new.haml
index d5d76d9..fe37201 100644
--- a/src/app/views/users/new.haml
+++ b/src/app/views/users/new.haml
@@ -14,13 +14,14 @@
%br
#user_card.user_form_card
%header.user-card-header
- %h2 Kenneth Keiter
+ %h2#first_name First name
+ %h2#last_name Last name
.user-card-content
%dl
%dt E-mail Address
- %dd kkeiter(a)redhat.com
+ %dd#email example(a)mail.com
%dt Username
- %dd kkeiter
+ %dd#login username
= form_for @user, :url => users_path, :html => {:class => 'generic'} do |f|
-if current_user
= render :partial => "form", :locals => { :form => f }
--
1.7.6.4
12 years, 6 months
[PATCH conductor 0/1] BZ741711 - Fix HWP CPU bug (resend)
by Matt Wagner
I sent this last week but got no response, and it's now lost in the noise, so I've rebased and am now resending. From my original posting:
Wes hit a bug with Hardware Profile matching. It turns out that HardwareProfile.generate_override_property_values was returning the front-end value for HWPs if the provider value was a range. This meant that if you designed a front-end profile with, say, nil CPUs (meaning "no prerefence"), and it matched onto a provider HWP with a range (1-4 for VMware), we'd end up passing the "nil CPUs" parameter to deltacloud when trying to start an instance.
This also adds a test case for this to try to keep us from having so many regressions here.
-- Matt
12 years, 6 months
Re: oauth python client test for iwhd
by Pete Zaitcev
On Tue, 4 Oct 2011 21:21:23 -0500
Steve Loranz <sloranz(a)redhat.com> wrote:
(cc: aeolus-devel)
> Here's the output I'm getting:
> ---
> Traceback (most recent call last):
> File "testWarehouseOauth.py", line 6, in <module>
> r, c = client.request('http://chifac2.usersys.redhat.com:9090', method='GET')
........
> File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/httplib2/__init__.py", line 300, in _parse_www_authenticate
> raise MalformedHeader("WWW-Authenticate")
> httplib2.MalformedHeader: WWW-Authenticate
Mine is similar, perhaps a different version:
[zaitcev@lembas iwhd-tip]$ python t/testoauth.py
Traceback (most recent call last):
File "t/testoauth.py", line 9, in <module>
r, c = client.request('http://localhost:9090', method='GET')
...................
File "/usr/lib/python2.7/site-packages/httplib2/__init__.py", line 254, in _parse_www_authenticate
(auth_scheme, the_rest) = authenticate.split(" ", 1)
ValueError: need more than 1 value to unpack
> I'm not yet sure what oauth2 doesn't like about the WWW-Authenticate
> header in the response. If you have any thoughts on it, I'm all ears.
RFC-5849 says:
Servers MAY indicate their support for the "OAuth" auth-scheme by
returning the HTTP "WWW-Authenticate" response header field upon
client requests for protected resources. As per [RFC2617], such a
response MAY include additional HTTP "WWW-Authenticate" header
fields:
For example:
WWW-Authenticate: OAuth realm="http://server.example.com/"
It says "MAY include" so, I thought that parameters were optional.
But RFC-2617 says:
auth-scheme = token
auth-param = token "=" ( token | quoted-string )
The 401 (Unauthorized) response message is used by an origin server
to challenge the authorization of a user agent. This response MUST
include a WWW-Authenticate header field containing at least one
challenge applicable to the requested resource. [...]
challenge = auth-scheme 1*SP 1#auth-param
[...]
The authentication parameter realm is defined for all authentication
schemes:
realm = "realm" "=" realm-value
realm-value = quoted-string
The realm directive (case-insensitive) is required for all
authentication schemes that issue a challenge.
So, basically I need to add a realm to the header. This is a little
unfortunate, because now I need to add a way to configure it, too.
Unless we're ok with realm="iwhd" or a hostname of the server, that is.
-- Pete
12 years, 6 months
[PATCH 0/9] Adds support for launch-time parameter collection
by Greg Blomquist
This patch adds the ability to collect launch-time parameters and propagate
those parameters to a config server.
To do this, several pieces have been added:
* add/manage config server connections per provider account
* updated deployable_xml to know about "services"
* UI elements added to collect launch-parameters (service parameters) during
deployment launch
* model elements added to capture launch parameters for later retrieval
* UI added to display launch parameters post-launch
12 years, 6 months
OAuth in iwhd preview patch
by Pete Zaitcev
Guys:
Below is what I have now for 2-legged OAuth in iwhd. It actually works,
with oauthtest2 from liboauth.
The patch is only a small piece, since it has no client, which we need
to run the tests, has no documentation, and no user list. However, it
retires most of the risk. We know that it can be done, this way.
The biggest risk left is interoperability with Aeolus.
BTW, the OAuth header looks like this:
Authorization: OAuth realm="http://example.org/", oauth_consumer_key="chiaki",
oauth_nonce="mitPzrhrCMHABJiYava_", oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1317182031", oauth_version="1.0",
oauth_signature="Ya36%2FkXTG5YATRx%2BWAXK9NXzZCg%3D"
-- Pete
diff --git a/configure.ac b/configure.ac
index e23d1fa..8b115cb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -70,6 +70,9 @@ AC_CHECK_LIB([uuid], [uuid_generate_random],
[AC_MSG_ERROR([Missing required uuid lib])])
AC_SUBST([UUID_LIB])
+dnl How to check properly?
+LIBS="$LIBS -loauth"
+
PKG_CHECK_MODULES([HAIL],[libhail >= 0.8])
AC_SUBST([HAIL_LIBS])
AC_SUBST([HAIL_CFLAGS])
@@ -97,6 +100,9 @@ AC_CACHE_CHECK([whether json_load_file takes 3 arguments],
AC_DEFINE_UNQUOTED([JANSSON_LOAD_FLAG], $iw_cv_func_jansson_flag,
[Define to "0," if json_load_file and json_loads require a flags arguments.])
+AC_CHECK_HEADER([oauth.h], ,
+ [AC_MSG_ERROR([Missing OAuth development library: liboauth-devel])])
+
# from http://www.gnu.org/software/autoconf-archive/
AX_BOOST_BASE
AX_BOOST_SYSTEM
diff --git a/rest.c b/rest.c
index 92f36cb..fec602c 100644
--- a/rest.c
+++ b/rest.c
@@ -15,12 +15,14 @@
#include <config.h>
+#include <ctype.h>
#include <error.h>
#include <fcntl.h>
#include <getopt.h>
#include <poll.h>
#include <pthread.h>
#include <semaphore.h>
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -33,6 +35,7 @@
#include <microhttpd.h>
#include <hstor.h> /* only for ARRAY_SIZE at this point */
#include <curl/curl.h>
+#include <oauth.h>
#include "configmake.h" /* for LOCALEDIR */
#include "dirname.h"
@@ -113,6 +116,9 @@ static unsigned short my_port = MY_PORT;
static LIST_HEAD(gc_list, _my_state) my_states; /* this keeps GC informed */
static pthread_mutex_t my_lock = PTHREAD_MUTEX_INITIALIZER;
static const char *log_name;
+static char my_hostname[HOST_NAME_MAX+1];
+static bool oauth = false;
+static const char *username, *userpass;
static const char *const (reserved_name[]) = {"_default", "_new", "_policy", "_query", NULL};
static const char *const (reserved_attr[]) = {"_attrs", "_bucket", "_date", "_etag", "_key", "_loc", "_size", NULL};
@@ -2091,6 +2097,454 @@ parse_url (const char *url, my_state *ms)
return eindex;
}
+/* TBD: evict this to "user.h" once -U is gone. */
+#define USERNAME_MAX 64
+#define USERPASS_MAX 64
+struct user {
+ char name[USERNAME_MAX+1];
+ char pass[USERPASS_MAX+1];
+};
+
+static struct user *
+user_lookup (const char *user)
+{
+ struct user *ret;
+
+ /*
+ * We do not have a real user table yet, so just compare with -U.
+ */
+ if (username == NULL || strcmp(user, username) != 0)
+ return NULL;
+
+ ret = malloc(sizeof(struct user));
+ if (!ret)
+ return NULL;
+ memset(ret,0,sizeof(struct user));
+ strcpy(ret->name, username);
+ strcpy(ret->pass, userpass);
+ return ret;
+}
+
+static char *
+rebuild_url(bool is_ssl, struct MHD_Connection *conn, const char *path)
+{
+ const char *val;
+ char *ret;
+ int rc;
+
+ /*
+ * Luckily for us, this header includes the colon-port.
+ * It really should be called "Netloc", not "Host".
+ */
+ val = MHD_lookup_connection_value(conn,MHD_HEADER_KIND,"Host");
+ if (!val) {
+ if (my_hostname[0] == 0) {
+ if (gethostname(my_hostname, HOST_NAME_MAX) != 0) {
+ /* TBD: This may flood - user-driven. */
+ error (0, errno, _("gethostname"));
+ return NULL;
+ }
+ my_hostname[HOST_NAME_MAX] = 0;
+ }
+ /* TBD: And port? But this is a fall-back anyway. */
+ val = my_hostname;
+ }
+
+ rc = asprintf(&ret, "%s://%s%s", is_ssl? "https": "http", val, path);
+ if (rc < 0) {
+ DPRINTF("No core");
+ return NULL;
+ }
+ return ret;
+}
+
+static const char *
+auth_type_check (const char *val, const char *type)
+{
+ const char *p;
+ size_t tlen = strlen(type);
+
+ p = val;
+ while (*p == ' ') {
+ if (*p == 0) {
+ return false;
+ }
+ p++;
+ }
+ if (strncmp(p, type, tlen) != 0)
+ return false;
+ p += tlen;
+ if (*p != ' ')
+ return false;
+ p++;
+ while (*p == ' ') {
+ if (*p == 0) {
+ return false;
+ }
+ p++;
+ }
+ return p;
+}
+
+/*
+ * Split up an Authorization header.
+ * Note that this decodes the strings.
+ */
+static bool
+auth_hdr_split (int *pargc, char ***pargv, const char *val)
+{
+ enum { ARGC_MAX = 20 }; /* better than 2-pass */
+ enum { VAL_MAX = 512 }; /* a constant is not great, but... */
+ enum {
+ ST_NONE, ST_ERR, ST_KEY, ST_EQ, ST_VAL, ST_Q2, ST_COM,
+ ST_PCENT1, ST_PCENT2
+ } state;
+ int argc;
+ char **argv;
+ const char *p;
+ const char *key;
+ size_t klen = 0;
+ size_t vlen = 0;
+ char vbuf[VAL_MAX+1];
+ unsigned int acc = 0, n;
+ char *arg;
+
+ if (!(val = auth_type_check(val, "OAuth")))
+ return false;
+
+ argv = malloc((ARGC_MAX+1) * sizeof(char*));
+ if (!argv) {
+ return false;
+ }
+ argc = 0;
+
+ arg = NULL;
+ state = ST_NONE;
+ key = NULL;
+ for (p = val; *p != 0; p++) {
+ switch (state) {
+ case ST_NONE:
+ if (*p == ' ') {
+ ;
+ }
+ else if (!isascii(*p) || !isalpha(*p)) {
+ state = ST_ERR;
+ }
+ else {
+ state = ST_KEY;
+ key = p;
+ }
+ break;
+ case ST_KEY:
+ if (*p == '=') {
+ state = ST_EQ;
+ klen = p-key;
+ }
+ break;
+ case ST_EQ:
+ if (*p == '"') {
+ state = ST_VAL;
+ vlen = 0;
+ }
+ else {
+ /*
+ * A compiler writer would've had an ulcer
+ * from this, because obviously we are going
+ * to recover in a dirty way. But whatever,
+ * all we want is an error indication.
+ */
+ state = ST_ERR;
+ }
+ break;
+ case ST_VAL:
+ if (*p == '"') {
+ vbuf[vlen] = 0;
+ state = ST_Q2;
+ }
+ else if (*p == '%') {
+ state = ST_PCENT1;
+ acc = 0;
+ }
+ else {
+ vbuf[vlen++] = *p;
+ }
+ break;
+ case ST_PCENT1:
+ if (isxdigit(*p)) {
+ if (*p <= '9') {
+ n = toupper(*p) - '0';
+ } else {
+ n = toupper(*p) - 'A' + 10;
+ }
+ acc = (acc << 4) | (n & 0x0f);
+ state = ST_PCENT2;
+ } else {
+ state = ST_ERR;
+ }
+ break;
+ case ST_PCENT2:
+ if (isxdigit(*p)) {
+ if (*p <= '9') {
+ n = toupper(*p) - '0';
+ } else {
+ n = toupper(*p) - 'A' + 10;
+ }
+ acc = (acc << 4) | (n & 0x0f);
+ if (iscntrl(acc))
+ acc = '?';
+ if (vlen >= VAL_MAX) {
+ state = ST_ERR;
+ break;
+ }
+ vbuf[vlen++] = acc;
+ state = ST_VAL;
+ }
+ else {
+ state = ST_ERR;
+ }
+ break;
+ case ST_Q2:
+ if (*p == ',') {
+ arg = malloc(klen+1+vlen+1);
+ if (!arg) {
+ state = ST_ERR;
+ break;
+ }
+ memcpy(arg, key, klen);
+ arg[klen] = '=';
+ memcpy(arg+klen+1, vbuf, vlen);
+ arg[klen+1+vlen] = 0;
+
+ state = ST_COM;
+ key = NULL;
+ }
+ else {
+ state = ST_ERR;
+ }
+ break;
+ case ST_COM:
+ if (*p == ' ') {
+ if (!arg) {
+ state = ST_NONE;
+ key = NULL;
+ break;
+ }
+ if (argc >= ARGC_MAX) {
+ /* TBD: error out immediately */
+ state = ST_ERR;
+ break;
+ }
+ argv[argc++] = arg;
+ arg = NULL;
+ state = ST_NONE;
+ key = NULL;
+ }
+ else {
+ state = ST_ERR;
+ }
+ default: // ST_ERR
+ if (*p == ',') {
+ state = ST_COM;
+ }
+ }
+ }
+
+ if (arg) {
+ DPRINTF("auth_hdr_split ended with arg %s\n", arg);
+ free (arg);
+ }
+
+ if (state == ST_Q2) {
+ if (key) {
+ arg = malloc(klen+1+vlen+1);
+ if (arg && argc < ARGC_MAX) {
+ memcpy(arg, key, klen);
+ arg[klen] = '=';
+ memcpy(arg+klen+1, vbuf, vlen);
+ arg[klen+1+vlen] = 0;
+ argv[argc++] = arg;
+ }
+ }
+ }
+ argv[argc] = NULL;
+
+ *pargc = argc;
+ *pargv = argv;
+ return true;
+}
+
+/* Extract the value from key="val". */
+static char *
+oauth_param_val(const char *arg) {
+ char *val;
+
+ val = strchr(arg, '=');
+ if (!val)
+ return NULL;
+ val++;
+ if (*val == 0)
+ return NULL;
+ return strdup(val);
+}
+
+/* clone of oauth_param_exists with minimal changes */
+static int
+oauth_param_find(char **argv, int argc, const char *key) {
+ int i;
+ size_t l= strlen(key);
+ for (i=0;i<argc;i++)
+ if (strlen(argv[i])>l && !strncmp(argv[i],key,l) && argv[i][l] == '=') return i;
+ return -1;
+}
+
+static int
+do_oauth (struct MHD_Connection *conn, my_state *ms,
+ const char *url, const char *method)
+{
+ const char *val;
+ struct MHD_Response *resp;
+ int argc;
+ char **argv;
+ int oargc;
+ char **oargv;
+ int x;
+ struct user *u;
+ char *sig_supplied, *sig_calculated;
+
+ val = MHD_lookup_connection_value(conn,MHD_HEADER_KIND,"Authorization");
+ if (!val) {
+ resp = MHD_create_response_from_data(0,NULL,MHD_NO,MHD_NO);
+ if (!resp) {
+ return -1;
+ }
+ MHD_add_response_header(resp,"WWW-Authenticate","OAuth");
+ MHD_queue_response(conn,MHD_HTTP_UNAUTHORIZED,resp);
+ MHD_destroy_response(resp);
+ return 1;
+ }
+
+ if (!auth_hdr_split(&argc, &argv, val)) {
+ do_resp(conn,NULL,MHD_HTTP_BAD_REQUEST,NULL,"400\r\n");
+ return -1;
+ }
+ if (verbose >= 2) {
+ int i;
+ printf("OAuth supplied [%d]\n", argc);
+ for (i = 0; i < argc; i++) {
+ printf(" %s\n", argv[i]);
+ }
+ }
+
+ x = oauth_param_find(argv,argc,"oauth_consumer_key");
+ if (x == -1) {
+ do_resp(conn,NULL,MHD_HTTP_BAD_REQUEST,NULL,"400 no user\r\n");
+ return -1;
+ }
+
+ u = user_lookup(oauth_param_val(argv[x]));
+ if (!u) {
+ do_resp(conn,NULL,MHD_HTTP_FORBIDDEN,NULL,"403 bad user\r\n");
+ return -1;
+ }
+
+ /*
+ * Putting marshalling arguments for and extracting results from
+ * oauth_sign_array2_process makes you dirty, but this way offloads
+ * some tricks to liboauth, so there.
+ * XXX - verify HMAC or other type
+ */
+ oargc = 1+argc; /* add a slot for URL */
+
+ /*
+ * If we just call malloc() here, we actually involve a function
+ * intercepted by GC. Then, glibc will abort inside liboauth
+ * oauth_sign_array2_process->xrealloc->free() => "invalid pointer".
+ * Solution: use a random liboauth function which allocates
+ * the memory we need. The result can be safely passed to liboauth.
+ */
+ oargv = malloc((oargc+1)*sizeof(char*));
+
+ memset((void*)oargv, '0', (oargc+1)*sizeof(char*));
+ ((char *)oargv)[(oargc+1)*sizeof(char*) - 1] = 0;
+ oargv = (char **) oauth_url_escape((char *)oargv);
+
+ if (!oargv) {
+ do_resp(conn,NULL,MHD_HTTP_INTERNAL_SERVER_ERROR,NULL,
+ "500\r\n");
+ return -1;
+ }
+ oargv[0] = rebuild_url(false, conn, url); /* TBD: SSL */
+ if (!oargv[0]) {
+ do_resp(conn,NULL,MHD_HTTP_INTERNAL_SERVER_ERROR,NULL,
+ "500\r\n");
+ return -1;
+ }
+
+ // no good, must filter
+ // memcpy(&oargv[1], argv, (argc+1)*sizeof(char*));
+
+ oargc = 1;
+
+ x = oauth_param_find(argv,argc,"oauth_nonce");
+ if (x == -1) {
+ do_resp(conn,NULL,MHD_HTTP_BAD_REQUEST,NULL,"400 no nonce\r\n");
+ return -1;
+ }
+ oargv[oargc++] = argv[x];
+
+ x = oauth_param_find(argv,argc,"oauth_timestamp");
+ if (x == -1) {
+ do_resp(conn,NULL,MHD_HTTP_BAD_REQUEST,NULL,
+ "400 no timestamp\r\n");
+ return -1;
+ }
+ oargv[oargc++] = argv[x];
+
+ oauth_sign_array2_process(&oargc, &oargv, NULL, OA_HMAC, method,
+ u->name, u->pass, NULL, NULL);
+ if (verbose >= 2) {
+ int i;
+ printf("OAuth calculated\n");
+ for (i = 0; i < oargc; i++) {
+ printf(" %s\n", oargv[i]);
+ }
+ }
+
+ /*
+ * We've got the signature, now verify.
+ */
+ x = oauth_param_find(argv,argc,"oauth_signature");
+ if (x == -1) {
+ do_resp(conn,NULL,MHD_HTTP_BAD_REQUEST,NULL,
+ "400 no signature\r\n");
+ return -1;
+ }
+ sig_supplied = oauth_param_val(argv[x]);
+
+ x = oauth_param_find(oargv,oargc,"oauth_signature");
+ if (x == -1) {
+ do_resp(conn,NULL,MHD_HTTP_INTERNAL_SERVER_ERROR,NULL,
+ "500 no signature\r\n");
+ return -1;
+ }
+ sig_calculated = oauth_param_val(oargv[x]);
+
+ if (strcmp(sig_supplied, sig_calculated) != 0) {
+ DPRINTF("OAuth signature mismatch");
+ return -1;
+ }
+ return 0;
+}
+
+static int kv_iter_dump(void *cls, enum MHD_ValueKind kind,
+ const char *key, const char *value)
+{
+ /* ok to use printf when MHD_USE_THREAD_PER_CONNECTION maybe? */
+ printf("%s: %s\n", key, value);
+
+ return MHD_YES;
+}
+
static int
access_handler_0 (void *cctx, struct MHD_Connection *conn, const char *url,
const char *method, const char *version, const char *data,
@@ -2099,10 +2553,24 @@ access_handler_0 (void *cctx, struct MHD_Connection *conn, const char *url,
unsigned int i;
url_type utype;
my_state *ms = *rctx;
+ int rc;
log_check();
+ if (verbose >= 2) {
+ printf(">> HTTP\n");
+ rc = MHD_get_connection_values(conn, MHD_HEADER_KIND,
+ kv_iter_dump, NULL);
+ printf(">> headers: %d\n", rc);
+ }
if (ms) {
+ if (oauth) {
+ rc = do_oauth(conn,ms,url,method);
+ if (rc < 0)
+ return MHD_NO;
+ if (rc > 0)
+ return MHD_YES;
+ }
return ms->handler(cctx,conn,url,method,version,
data,data_size,rctx);
}
@@ -2131,12 +2599,20 @@ access_handler_0 (void *cctx, struct MHD_Connection *conn, const char *url,
ms->conn = conn;
*rctx = ms;
pthread_mutex_lock(&my_lock);
- LIST_INSERT_HEAD(&my_states, ms, gc_link);
+ LIST_INSERT_HEAD(&my_states,ms,gc_link);
pthread_mutex_unlock(&my_lock);
+ if (oauth) {
+ rc = do_oauth(conn,ms,url,method);
+ if (rc < 0)
+ return MHD_NO;
+ if (rc > 0)
+ return MHD_YES;
+ }
return ms->handler(cctx,conn,url,method,version,
data,data_size,rctx);
}
+ /* This is *unauthenticated*. Remove altogether? TBD */
if (!strcmp(method,"QUIT")) {
(void)sem_post((sem_t *)cctx);
return MHD_NO;
@@ -2194,7 +2670,9 @@ static const struct option my_options[] = {
{ "db", required_argument, NULL, 'd' },
{ "logfile", required_argument, NULL, 'l' },
{ "master", required_argument, NULL, 'm' },
+ { "oauth", no_argument, NULL, 'o' },
{ "port", required_argument, NULL, 'p' },
+ { "usercred", required_argument, NULL, 'U' },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, GETOPT_VERSION_CHAR },
{ "help", no_argument, NULL, GETOPT_HELP_CHAR },
@@ -2222,7 +2700,9 @@ A configuration file must be specified.\n\
-d, --db=HOST_PORT database server as ip[:port]\n\
-l, --logfile=FILE logfile (default stdout/stderr)\n\
-m, --master=HOST_PORT master (upstream) server as ip[:port]\n\
+ -o, --oauth enable OAuth\n\
-p, --port=PORT alternate listen port (default 9090)\n\
+ -U, --usercred=U:P singleton pair of username:password\n\
-v, --verbose verbose/debug output\n\
\n\
--help display this help and exit\n\
@@ -2275,6 +2755,7 @@ main (int argc, char **argv)
sem_t the_sem;
bool autostart = false;
char *cfg_file = NULL;
+ char *usercred = NULL;
set_program_name (argv[0]);
setlocale (LC_ALL, "");
@@ -2287,7 +2768,8 @@ main (int argc, char **argv)
db_host = xstrdup ("localhost");
for (;;)
- switch (getopt_long(argc,argv,"ac:d:l:m:p:v",my_options,NULL)) {
+ switch (getopt_long(argc,argv,"ac:d:l:m:op:U:v",my_options,NULL))
+ {
case 'a':
autostart = true;
break;
@@ -2308,10 +2790,16 @@ main (int argc, char **argv)
free (master_host); master_host = NULL;
extract_host_port (optarg, &master_host, &master_port);
break;
+ case 'o':
+ oauth = true;
+ break;
case 'p':
assert (optarg);
my_port = get_port (optarg);
break;
+ case 'U': /* Uppercase because very temporary until -u appears. */
+ usercred = optarg;
+ break;
case 'v':
++verbose;
break;
@@ -2366,6 +2854,30 @@ args_done:
usage (EXIT_FAILURE);
}
+ if (usercred) {
+ const char *p = strchr(usercred,':');
+ if (!p) {
+ error (0, 0, _("The -U argument must contain a colon"));
+ usage (EXIT_FAILURE);
+ }
+ if (p == usercred) {
+ error (0, 0,
+ _("The user part of -U argument is empty"));
+ usage (EXIT_FAILURE);
+ }
+ username = strndup(usercred,p-usercred);
+ userpass = strdup(p+1);
+ if (!username || !userpass) {
+ error (EXIT_FAILURE, 0, _("No core"));
+ }
+ if (strlen(username) > USERNAME_MAX) {
+ error (EXIT_FAILURE, 0, _("User name too long"));
+ }
+ if (strlen(userpass) > USERPASS_MAX) {
+ error (EXIT_FAILURE, 0, _("User password too long"));
+ }
+ }
+
char *t;
char const *tmpdir = ((t = getenv ("TMPDIR")) ? t : "/tmp");
tmpfile_template = xasprintf ("%s/iwhd.XXXXXX", tmpdir);
@@ -2382,6 +2894,9 @@ args_done:
printf("db is at %s:%u\n",db_host,db_port);
printf("will listen on port %u\n",my_port);
printf("my location is \"%s\"\n",me);
+ if (oauth) {
+ printf("autheticated with OAuth\n");
+ }
if (fflush(stdout) || ferror(stdout))
error(EXIT_FAILURE, 0, _("write failed"));
}
12 years, 6 months