summaryrefslogtreecommitdiffabout
authorMichael Krelin <hacker@klever.net>2008-02-04 22:39:59 (UTC)
committer Michael Krelin <hacker@klever.net>2008-02-04 22:39:59 (UTC)
commit9163a26ec8839a31df888920418280a62ebc5595 (patch) (side-by-side diff)
tree55339b4ecf0a3f24817eb5cc1b0b24f831ac895b
parentc0eeee1cfd41d0f5f6ff6ac3d6fe021421376a69 (diff)
downloadlibopkele-9163a26ec8839a31df888920418280a62ebc5595.zip
libopkele-9163a26ec8839a31df888920418280a62ebc5595.tar.gz
libopkele-9163a26ec8839a31df888920418280a62ebc5595.tar.bz2
reworked extensions framework
* changed {checkid,id_res}_hook to {rp,op}_{checkid,id_res}_hook * deprecated older hooks, although implemented it in sreg and chain extensions * added extension processing to basic_op * added sreg to test OP Signed-off-by: Michael Krelin <hacker@klever.net>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--include/opkele/basic_op.h3
-rw-r--r--include/opkele/extension.h49
-rw-r--r--include/opkele/extension_chain.h6
-rw-r--r--include/opkele/sreg.h31
-rw-r--r--lib/basic_op.cc5
-rw-r--r--lib/basic_rp.cc4
-rw-r--r--lib/extension.cc25
-rw-r--r--lib/extension_chain.cc27
-rw-r--r--lib/sreg.cc28
-rw-r--r--test/OP.cc10
10 files changed, 121 insertions, 67 deletions
diff --git a/include/opkele/basic_op.h b/include/opkele/basic_op.h
index 7f4e481..5bba1bf 100644
--- a/include/opkele/basic_op.h
+++ b/include/opkele/basic_op.h
@@ -37,13 +37,14 @@ namespace opkele {
basic_openid_message& associate(
basic_openid_message& oum,
const basic_openid_message& inm);
void checkid_(const basic_openid_message& inm,extension_t *ext=0);
- basic_openid_message& id_res(basic_openid_message& om);
+ basic_openid_message& id_res(basic_openid_message& om,
+ extension_t *ext=0);
basic_openid_message& cancel(basic_openid_message& om);
basic_openid_message& error(basic_openid_message& om,
const string& error,const string& contact,
const string& reference );
basic_openid_message& setup_needed(
basic_openid_message& oum,const basic_openid_message& inm);
diff --git a/include/opkele/extension.h b/include/opkele/extension.h
index 3ee25ee..37bcb90 100644
--- a/include/opkele/extension.h
+++ b/include/opkele/extension.h
@@ -3,12 +3,13 @@
/**
* @file
* @brief extensions framework basics
*/
+#include <opkele/opkele-config.h>
#include <opkele/types.h>
namespace opkele {
/**
* OpenID extension hooks base class
@@ -16,45 +17,39 @@ namespace opkele {
class extension_t {
public:
virtual ~extension_t() { }
/**
- * hook called by consumer before submitting data to OpenID server.
- * It is supposed to manipulate parameters list.
- * @param p parameters about to be submitted to server
- * @param identity identity being verified. It may differ from the
- * one available in parameters list in case of delegation
- * @see consumer_t::checkid_
- * @see consumer_t::checkid_immediate
- * @see consumer_t::checkid_setup
+ * hook called by RP before submitting the message to OP.
+ * @param om openid message to be submit
*/
- virtual void checkid_hook(basic_openid_message& om);
+ virtual void rp_checkid_hook(basic_openid_message& om);
+
/**
- * hook called by consumer after identity information received from
- * OpenID server is verified.
- * @param p parameters received from server
- * @param sp signed parameters received from server with 'openid.'
- * leader stripped
- * @param identity identity confirmed. May differ from the one
- * available in parameters list in case of delegation. May also be
- * empty which means - extract one from parameters
- * @see consumer_t::id_res
+ * hook called by RP after verifying information received from OP.
+ * @param om openid message received
+ * @param sp signed part of the message
*/
- virtual void id_res_hook(const basic_openid_message& om,const basic_openid_message& sp);
+ virtual void rp_id_res_hook(const basic_openid_message& om,
+ const basic_openid_message& sp);
/**
- * hook called by server before returning information to consumer.
- * The hook may manipulate output parameters. It is important to
- * note that modified pout["signed"] is used for signing response.
- * @param pin request parameters list with "openid." prefix
- * @param pout response parameters list without "openid." prefix
- * @see server_t::checkid_
- * @see server_t::checkid_immediate
- * @see server_t::checkid_setup
+ * hook called by OP after parsing incoming message
+ * @param inm message received from RP
+ */
+ virtual void op_checkid_hook(const basic_openid_message& inm);
+ /**
+ * hook called by OP before signing the reply to RP
+ * @param oum message to be sent to RP
*/
+ virtual void op_id_res_hook(basic_openid_message& oum);
+
+ virtual void checkid_hook(basic_openid_message& om) OPKELE_DEPRECATE;
+ virtual void id_res_hook(const basic_openid_message& om,
+ const basic_openid_message& sp) OPKELE_DEPRECATE;
virtual void checkid_hook(const basic_openid_message& inm,basic_openid_message& oum);
/**
* Casts the object to pointer to itself. For convenient passing
* of pointer.
*/
diff --git a/include/opkele/extension_chain.h b/include/opkele/extension_chain.h
index fb9bc84..9692934 100644
--- a/include/opkele/extension_chain.h
+++ b/include/opkele/extension_chain.h
@@ -25,12 +25,18 @@ namespace opkele {
extension_chain_t() { }
/**
* Create extension chain with a single extension in it
*/
extension_chain_t(extension_t *e) { push_back(e); }
+ virtual void rp_checkid_hook(basic_openid_message& om);
+ virtual void rp_id_res_hook(const basic_openid_message& om,
+ const basic_openid_message& sp);
+ virtual void op_checkid_hook(const basic_openid_message& inm);
+ virtual void op_id_res_hook(basic_openid_message& oum);
+
virtual void checkid_hook(basic_openid_message& om);
virtual void id_res_hook(const basic_openid_message& om,const basic_openid_message& sp);
virtual void checkid_hook(const basic_openid_message& inm,basic_openid_message& oum);
};
}
diff --git a/include/opkele/sreg.h b/include/opkele/sreg.h
index 24cb315..513e221 100644
--- a/include/opkele/sreg.h
+++ b/include/opkele/sreg.h
@@ -132,24 +132,23 @@ namespace opkele {
* @param pu policy url
* @see policy_url
*/
sreg_t(long fr=fields_NONE,long fo=fields_NONE,const string& pu="")
: fields_required(fr), fields_optional(fo), policy_url(pu), has_fields(0) { }
- /**
- * Implementation of consumer's checkid hook
- */
+ virtual void rp_checkid_hook(basic_openid_message& om);
+ virtual void rp_id_res_hook(const basic_openid_message& om,
+ const basic_openid_message& sp);
+ virtual void op_checkid_hook(const basic_openid_message& inm);
+ virtual void op_id_res_hook(basic_openid_message& oum);
+
virtual void checkid_hook(basic_openid_message& om);
- /**
- * Implementation of consumer's id_res hook
- */
- virtual void id_res_hook(const basic_openid_message& om,const basic_openid_message& sp);
- /**
- * Implementation of server's checkid_hook
- */
- virtual void checkid_hook(const basic_openid_message& inm,basic_openid_message& oum);
+ virtual void id_res_hook(const basic_openid_message& om,
+ const basic_openid_message& sp);
+ virtual void checkid_hook(const basic_openid_message& inm,
+ basic_openid_message& oum);
/**
* Check and see if we have value for some particular field.
* @param fb field in question
* @see fieldbit_t
* @return true if the value is available
@@ -188,16 +187,18 @@ namespace opkele {
/**
* Function called after parsing sreg request to set up response
* fields. The default implementation tries to send as much fields
* as we have. The function is supposed to set the data and
* fields_response.
* @see fields_response
- * @param pin input request parameters with "openid." prefix
- * @param pout output request parameters without "openid." prefix.
- * @see checkid_hook(const params_t&,params_t&)
+ * @param inm incoming openid message
+ * @param oum outgoing openid message
*/
- virtual void setup_response(const basic_openid_message& inm,basic_openid_message& oum);
+ virtual void setup_response(const basic_openid_message& inm,
+ basic_openid_message& oum);
+
+ virtual void setup_response();
};
}
#endif /* __OPKELE_SREG_H */
diff --git a/lib/basic_op.cc b/lib/basic_op.cc
index c89d1d7..9e2ea5a 100644
--- a/lib/basic_op.cc
+++ b/lib/basic_op.cc
@@ -190,15 +190,17 @@ namespace opkele {
}catch(failed_lookup&) {
if(openid2 && inm.has_field("claimed_id"))
throw bad_input(OPKELE_CP_
"claimed_id and identity must be either both present or both absent");
}
verify_return_to();
+ if(ext) ext->op_checkid_hook(inm);
}
- basic_openid_message& basic_op::id_res(basic_openid_message& om) {
+ basic_openid_message& basic_op::id_res(basic_openid_message& om,
+ extension_t *ext) {
assert(assoc);
assert(!return_to.empty());
assert(!is_id_select());
time_t now = time(0);
struct tm gmt; gmtime_r(&now,&gmt);
char w3timestr[24];
@@ -221,12 +223,13 @@ namespace opkele {
if(!invalidate_handle.empty()) {
om.set_field("invalidate_handle",invalidate_handle);
ats += ",invalidate_handle";
}
om.set_field("assoc_handle",assoc->handle());
om.add_to_signed(ats);
+ if(ext) ext->op_id_res_hook(om);
om.set_field("sig",util::base64_signature(assoc,om));
return om;
}
basic_openid_message& basic_op::cancel(basic_openid_message& om) {
assert(!return_to.empty());
diff --git a/lib/basic_rp.cc b/lib/basic_rp.cc
index a884583..bd45d99 100644
--- a/lib/basic_rp.cc
+++ b/lib/basic_rp.cc
@@ -126,13 +126,13 @@ namespace opkele {
}catch(dumb_RP& drp) {
}catch(failed_lookup& fl) {
try {
rv.set_field("assoc_handle",associate(ep.uri)->handle());
}catch(dumb_RP& drp) { }
} OPKELE_RETHROW
- if(ext) ext->checkid_hook(rv);
+ if(ext) ext->rp_checkid_hook(rv);
return rv;
}
class signed_part_message_proxy : public basic_openid_message {
public:
const basic_openid_message& x;
@@ -272,13 +272,13 @@ namespace opkele {
om.get_field("op_endpoint"),
om.get_field("claimed_id"),
om.get_field("identity") );
}
}
- if(ext) ext->id_res_hook(om,signeds);
+ if(ext) ext->rp_id_res_hook(om,signeds);
}
void basic_RP::check_authentication(const string& OP,
const basic_openid_message& om){
openid_message_t res;
static const string checkauthmode = "check_authentication";
diff --git a/lib/extension.cc b/lib/extension.cc
index 6451249..f7aaea5 100644
--- a/lib/extension.cc
+++ b/lib/extension.cc
@@ -1,15 +1,26 @@
#include <opkele/exception.h>
#include <opkele/extension.h>
namespace opkele {
+ void extension_t::rp_checkid_hook(basic_openid_message&) {
+ throw not_implemented(OPKELE_CP_ "RP checkid_* hook not implemented"); }
+ void extension_t::rp_id_res_hook(const basic_openid_message&,
+ const basic_openid_message&) {
+ throw not_implemented(OPKELE_CP_ "RP id_res hook not implemented"); }
+
+ void extension_t::op_checkid_hook(const basic_openid_message&) {
+ throw not_implemented(OPKELE_CP_ "OP checkid_* hook not implemented"); }
+ void extension_t::op_id_res_hook(basic_openid_message& om) {
+ throw not_implemented(OPKELE_CP_ "OP id_res hook not implemented"); }
+
+
void extension_t::checkid_hook(basic_openid_message&) {
- throw not_implemented(OPKELE_CP_ "Consumer checkid_hook not implemented");
- }
- void extension_t::id_res_hook(const basic_openid_message&,const basic_openid_message&) {
- throw not_implemented(OPKELE_CP_ "Consumer id_res_hook not implemented");
- }
+ throw not_implemented(OPKELE_CP_ "deprecated consumer checkid_* hook not implemented"); }
+ void extension_t::id_res_hook(const basic_openid_message&,
+ const basic_openid_message&) {
+ throw not_implemented(OPKELE_CP_ "deprecated consumer id_res hook not implemented"); }
+
void extension_t::checkid_hook(const basic_openid_message&,basic_openid_message&) {
- throw not_implemented(OPKELE_CP_ "Server checkid_hook not implemented");
- }
+ throw not_implemented(OPKELE_CP_ "deprecated server checkid hook not implemented"); }
}
diff --git a/lib/extension_chain.cc b/lib/extension_chain.cc
index 5c2afd9..5483740 100644
--- a/lib/extension_chain.cc
+++ b/lib/extension_chain.cc
@@ -1,16 +1,27 @@
#include <cstdarg>
#include <opkele/extension_chain.h>
namespace opkele {
+ void extension_chain_t::rp_checkid_hook(basic_openid_message& om) {
+ for(iterator i=begin();i!=end();++i) (*i)->rp_checkid_hook(om); }
+ void extension_chain_t::rp_id_res_hook(const basic_openid_message& om,
+ const basic_openid_message& sp) {
+ for(iterator i=begin();i!=end();++i) (*i)->rp_id_res_hook(om,sp); }
+
+ void extension_chain_t::op_checkid_hook(const basic_openid_message& inm) {
+ for(iterator i=begin();i!=end();++i) (*i)->op_checkid_hook(inm); }
+ void extension_chain_t::op_id_res_hook(basic_openid_message& oum) {
+ for(iterator i=begin();i!=end();++i) (*i)->op_id_res_hook(oum); }
+
+
void extension_chain_t::checkid_hook(basic_openid_message& om){
- for(iterator i=begin();i!=end();++i) (*i)->checkid_hook(om);
- }
- void extension_chain_t::id_res_hook(const basic_openid_message& om,const basic_openid_message& sp) {
- for(iterator i=begin();i!=end();++i) (*i)->id_res_hook(om,sp);
- }
- void extension_chain_t::checkid_hook(const basic_openid_message& inm,basic_openid_message& oum) {
- for(iterator i=begin();i!=end();++i) (*i)->checkid_hook(inm,oum);
- }
+ for(iterator i=begin();i!=end();++i) (*i)->checkid_hook(om); }
+ void extension_chain_t::id_res_hook(const basic_openid_message& om,
+ const basic_openid_message& sp) {
+ for(iterator i=begin();i!=end();++i) (*i)->id_res_hook(om,sp); }
+ void extension_chain_t::checkid_hook(const basic_openid_message& inm,
+ basic_openid_message& oum) {
+ for(iterator i=begin();i!=end();++i) (*i)->checkid_hook(inm,oum); }
}
diff --git a/lib/sreg.cc b/lib/sreg.cc
index 7e2d588..b40cd45 100644
--- a/lib/sreg.cc
+++ b/lib/sreg.cc
@@ -25,13 +25,13 @@ namespace opkele {
typedef const struct _sreg_field *fields_iterator;
bool operator==(const struct _sreg_field& fd,const string& fn) {
return fd.fieldname==fn;
}
- void sreg_t::checkid_hook(basic_openid_message& om) {
+ void sreg_t::rp_checkid_hook(basic_openid_message& om) {
string fr, fo;
for(fields_iterator f=fields_BEGIN;f<fields_END;++f) {
if(f->fieldbit&fields_required) {
if(!fr.empty()) fr+=",";
fr += f->fieldname;
}
@@ -43,13 +43,17 @@ namespace opkele {
string pfx = om.allocate_ns(OIURI_SREG11,"sreg");
if(!fr.empty()) om.set_field(pfx+".required",fr);
if(!fo.empty()) om.set_field(pfx+".optional",fo);
if(!policy_url.empty()) om.set_field(pfx+".policy_url",policy_url);
}
- void sreg_t::id_res_hook(const basic_openid_message& om,const basic_openid_message& sp) {
+ void sreg_t::checkid_hook(basic_openid_message& om) {
+ rp_checkid_hook(om); }
+
+ void sreg_t::rp_id_res_hook(const basic_openid_message& om,
+ const basic_openid_message& sp) {
clear();
string pfx;
try {
pfx = om.find_ns(OIURI_SREG11,"sreg");
}catch(failed_lookup& fl) {
try {
@@ -64,12 +68,16 @@ namespace opkele {
if(!sp.has_field(fn)) continue;
has_fields |= f->fieldbit;
response[f->fieldbit]=sp.get_field(fn);
}
}
+ void sreg_t::id_res_hook(const basic_openid_message& om,
+ const basic_openid_message& sp) {
+ rp_id_res_hook(om,sp); }
+
const string& sreg_t::get_field(fieldbit_t fb) const {
response_t::const_iterator i = response.find(fb);
if(i==response.end())
throw failed_lookup(OPKELE_CP_ "no field data available");
return i->second;
}
@@ -102,13 +110,13 @@ namespace opkele {
if(f!=fields_END)
rv |= f->fieldbit;
}
return rv;
}
- void sreg_t::checkid_hook(const basic_openid_message& inm,basic_openid_message& oum) {
+ void sreg_t::op_checkid_hook(const basic_openid_message& inm) {
string ins = inm.find_ns(OIURI_SREG11,"sreg");
fields_optional = 0; fields_required = 0; policy_url.erase();
fields_response = 0;
try {
string fl = inm.get_field(ins+".required");
fields_required = fields_list_to_bitmask(fl);
@@ -117,13 +125,15 @@ namespace opkele {
string fl = inm.get_field(ins+".optional");
fields_optional = fields_list_to_bitmask(fl);
}catch(failed_lookup&) { }
try {
policy_url = inm.get_field(ins+".policy_url");
}catch(failed_lookup&) { }
- setup_response(inm,oum);
+ }
+
+ void sreg_t::op_id_res_hook(basic_openid_message& oum) {
string ons = oum.allocate_ns(OIURI_SREG11,"sreg");
fields_response &= has_fields;
string signeds = "ns."+ons;
for(fields_iterator f=fields_BEGIN;f<fields_END;++f) {
if(!(f->fieldbit&fields_response)) continue;
signeds +=',';
@@ -131,10 +141,20 @@ namespace opkele {
signeds += pn;
oum.set_field(pn,get_field(f->fieldbit));
}
oum.add_to_signed(signeds);
}
+ void sreg_t::checkid_hook(const basic_openid_message& inm,
+ basic_openid_message& oum) {
+ op_checkid_hook(inm);
+ setup_response(inm,oum);
+ op_id_res_hook(oum);
+ }
+
void sreg_t::setup_response(const basic_openid_message& /* inm */,basic_openid_message& /* oum */) {
+ setup_response();
+ }
+ void sreg_t::setup_response() {
fields_response = (fields_required|fields_optional)&has_fields;
}
}
diff --git a/test/OP.cc b/test/OP.cc
index 1196c0c..c919d7f 100644
--- a/test/OP.cc
+++ b/test/OP.cc
@@ -11,12 +11,13 @@ using namespace std;
#include <opkele/util.h>
#include <opkele/uris.h>
#include <opkele/extension.h>
#include <opkele/association.h>
#include <opkele/debug.h>
#include <opkele/verify_op.h>
+#include <opkele/sreg.h>
#include "sqlite.h"
#include "kingate_openid_message.h"
static const string get_self_url(const kingate::cgi_gateway& gw) {
bool s = gw.has_meta("SSL_PROTOCOL_VERSION");
@@ -266,24 +267,29 @@ int main(int argc,char *argv[]) {
"</xrds:XRDS>";
}else if(op=="id_res" || op=="cancel") {
kingate_openid_message_t inm(gw);
example_op_t OP(gw);
if(gw.get_param("hts_id")!=OP.htc.get_value())
throw opkele::exception(OPKELE_CP_ "toying around, huh?");
- OP.checkid_(inm,0);
+ opkele::sreg_t sreg;
+ OP.checkid_(inm,sreg);
OP.cookie_header(cout);
opkele::openid_message_t om;
if(op=="id_res") {
if(!OP.get_authorized())
throw opkele::exception(OPKELE_CP_ "not logged in");
if(OP.is_id_select()) {
OP.select_identity( get_self_url(gw), get_self_url(gw) );
}
+ sreg.set_field(opkele::sreg_t::field_nickname,"anonymous");
+ sreg.set_field(opkele::sreg_t::field_fullname,"Ann O'Nymus");
+ sreg.set_field(opkele::sreg_t::field_gender,"F");
+ sreg.setup_response();
cout <<
"Status: 302 Going back to RP with id_res\n"
- "Location: " << OP.id_res(om).append_query(OP.get_return_to())
+ "Location: " << OP.id_res(om,sreg).append_query(OP.get_return_to())
<< "\n\n";
}else{
cout <<
"Status: 302 Going back to RP with cancel\n"
"Location: " << OP.cancel(om).append_query(OP.get_return_to())
<< "\n\n";