summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--include/opkele/basic_op.h119
-rw-r--r--include/opkele/verify_op.h2
-rw-r--r--lib/basic_op.cc38
-rw-r--r--lib/verify_op.cc2
-rw-r--r--test/OP.cc2
5 files changed, 134 insertions, 29 deletions
diff --git a/include/opkele/basic_op.h b/include/opkele/basic_op.h
index 5bba1bf..4daed02 100644
--- a/include/opkele/basic_op.h
+++ b/include/opkele/basic_op.h
@@ -5,13 +5,13 @@
#include <opkele/types.h>
#include <opkele/extension.h>
namespace opkele {
using std::string;
- class basic_op {
+ class basic_OP {
public:
mode_t mode;
assoc_t assoc;
bool openid2;
string return_to;
string realm;
@@ -32,38 +32,143 @@ namespace opkele {
bool is_id_select() const;
void select_identity(const string& c,const string& i);
void set_claimed_id(const string& c);
+ /** @name OpenID operations
+ * @{
+ */
+ /**
+ * Establish association with RP
+ * @param oum reply message
+ * @param inm request message
+ */
basic_openid_message& associate(
basic_openid_message& oum,
const basic_openid_message& inm);
+ /**
+ * Parse the checkid_* request. The function parses input message,
+ * retrieves the information needed for further processing,
+ * verifies what can be verified at this stage.
+ * @param inm incoming OpenID message
+ * @param ext extension/chain of extensions supported
+ */
void checkid_(const basic_openid_message& inm,extension_t *ext=0);
+ /**
+ * Build and sign a positive assertion message
+ * @param om outpu OpenID message
+ * @param ext extension/chain of extensions supported
+ * @return reference to om
+ */
basic_openid_message& id_res(basic_openid_message& om,
extension_t *ext=0);
+ /**
+ * Build a 'cancel' negative assertion
+ * @param om output OpenID message
+ * @return reference to om
+ */
basic_openid_message& cancel(basic_openid_message& om);
+ /**
+ * Build an 'error' reply
+ * @param om output OpenID message
+ * @param error a human-readable message indicating the cause
+ * @param contact contact address for the server administrator (can be empty)
+ * @param reference a reference token (can be empty)
+ * @return reference to om
+ */
basic_openid_message& error(basic_openid_message& om,
const string& error,const string& contact,
const string& reference );
+ /**
+ * Build a setup_needed reply to checkid_immediate request
+ * @param oum output OpenID message
+ * @param inm incoming OpenID request being processed
+ * @return reference to oum
+ */
basic_openid_message& setup_needed(
basic_openid_message& oum,const basic_openid_message& inm);
+ /**
+ * Process check_authentication request
+ * @param oum output OpenID message
+ * @param inm incoming request
+ * @return reference to oum
+ */
basic_openid_message& check_authentication(
basic_openid_message& oum,const basic_openid_message& inm);
-
+ /**
+ * @}
+ */
+
+ /**
+ * Verify return_to url. The default implementation checks whether
+ * return_to URI matches the realm
+ * @throw bad_realm in case of invalid realm
+ * @throw bad_return_to if return_to doesn't match the realm
+ * @see verify_op::verify_return_to()
+ */
virtual void verify_return_to();
- virtual assoc_t alloc_assoc(const string& t,size_t kl,bool sl) = 0;
- virtual assoc_t retrieve_assoc(const string& h) = 0;
-
- virtual string& alloc_nonce(string& nonce,bool sl) = 0;
+ /**
+ * @name Global persistent store API
+ * These functions are related to the associations with RPs storage
+ * and retrieval and nonce management.
+ * @{
+ */
+ /**
+ * Allocate association.
+ * @param type association type
+ * @param kl association key length
+ * @param sl true if the association is stateless
+ * @return association object
+ */
+ virtual assoc_t alloc_assoc(const string& type,size_t kl,bool sl) = 0;
+ /**
+ * Retrieve valid unexpired association
+ * @param handle association handle
+ * @return association object
+ */
+ virtual assoc_t retrieve_assoc(const string& handle) = 0;
+ /**
+ * Allocate nonce.
+ * @param nonce input-output parameter containing timestamp part of
+ * the nonce on input
+ * @param sl true if the nonce is
+ * @return reference to nonce
+ * @throw failed_lookup if no such valid unexpired association
+ * could be retrieved
+ */
+ virtual string& alloc_nonce(string& nonce) = 0;
+ /**
+ * Check nonce validity
+ * @param nonce nonce to check
+ * @return true if nonce found and isn't yet invalidated
+ */
virtual bool check_nonce(const string& nonce) = 0;
+ /**
+ * Invalidate nonce
+ * @param nonce nonce to check
+ */
virtual void invalidate_nonce(const string& nonce) = 0;
-
+ /**
+ * @}
+ */
+
+ /**
+ * @name Site particulars API
+ * @{
+ */
+ /**
+ * Query the absolute URL of the op endpoint
+ * @return fully qualified url of the OP endpoint
+ */
virtual const string get_op_endpoint() const = 0;
+ /**
+ * @}
+ */
};
}
#endif /* __OPKELE_BASIC_OP_H */
diff --git a/include/opkele/verify_op.h b/include/opkele/verify_op.h
index f5c97b2..6c3c386 100644
--- a/include/opkele/verify_op.h
+++ b/include/opkele/verify_op.h
@@ -2,13 +2,13 @@
#define __OPKELE_VERIFY_OP_H
#include <opkele/basic_op.h>
namespace opkele {
- class verify_op : public basic_op {
+ class verify_op : public basic_OP {
public:
void verify_return_to();
};
}
diff --git a/lib/basic_op.cc b/lib/basic_op.cc
index 7a2dbd2..18446dc 100644
--- a/lib/basic_op.cc
+++ b/lib/basic_op.cc
@@ -7,61 +7,61 @@
#include <opkele/exception.h>
#include <opkele/util.h>
#include <opkele/uris.h>
namespace opkele {
- void basic_op::reset_vars() {
+ void basic_OP::reset_vars() {
assoc.reset();
return_to.clear(); realm.clear();
claimed_id.clear(); identity.clear();
invalidate_handle.clear();
}
- bool basic_op::has_return_to() const {
+ bool basic_OP::has_return_to() const {
return !return_to.empty();
}
- const string& basic_op::get_return_to() const {
+ const string& basic_OP::get_return_to() const {
if(return_to.empty())
throw no_return_to(OPKELE_CP_ "No return_to URL provided with request");
return return_to;
}
- const string& basic_op::get_realm() const {
+ const string& basic_OP::get_realm() const {
assert(!realm.empty());
return realm;
}
- bool basic_op::has_identity() const {
+ bool basic_OP::has_identity() const {
return !identity.empty();
}
- const string& basic_op::get_claimed_id() const {
+ const string& basic_OP::get_claimed_id() const {
if(claimed_id.empty())
throw non_identity(OPKELE_CP_ "attempting to retrieve claimed_id of non-identity related request");
assert(!identity.empty());
return claimed_id;
}
- const string& basic_op::get_identity() const {
+ const string& basic_OP::get_identity() const {
if(identity.empty())
throw non_identity(OPKELE_CP_ "attempting to retrieve identity of non-identity related request");
assert(!claimed_id.empty());
return identity;
}
- bool basic_op::is_id_select() const {
+ bool basic_OP::is_id_select() const {
return identity==IDURI_SELECT20;
}
- void basic_op::select_identity(const string& c,const string& i) {
+ void basic_OP::select_identity(const string& c,const string& i) {
claimed_id = c; identity = i;
}
- void basic_op::set_claimed_id(const string& c) {
+ void basic_OP::set_claimed_id(const string& c) {
claimed_id = c;
}
- basic_openid_message& basic_op::associate(
+ basic_openid_message& basic_OP::associate(
basic_openid_message& oum,
const basic_openid_message& inm) try {
assert(inm.get_field("mode")=="associate");
util::dh_t dh;
util::bignum_t c_pub;
unsigned char key_digest[SHA256_DIGEST_LENGTH];
@@ -128,13 +128,13 @@ namespace opkele {
oum.set_field("error_code","unsupported-type");
oum.set_field("session_type","DH-SHA256");
oum.set_field("assoc_type","HMAC-SHA256");
return oum;
}
- void basic_op::checkid_(const basic_openid_message& inm,
+ void basic_OP::checkid_(const basic_openid_message& inm,
extension_t *ext) {
reset_vars();
string mode = inm.get_field("mode");
if(mode=="checkid_setup")
mode = mode_checkid_setup;
else if(mode=="checkid_immediate")
@@ -190,13 +190,13 @@ namespace opkele {
"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(!return_to.empty());
assert(!is_id_select());
if(!assoc) {
assoc = alloc_assoc("HMAC-SHA256",SHA256_DIGEST_LENGTH,true);
}
@@ -215,44 +215,44 @@ namespace opkele {
om.set_field("identity",identity);
om.set_field("claimed_id",claimed_id);
ats += ",identity,claimed_id";
}
om.set_field("return_to",return_to);
string nonce = w3timestr;
- om.set_field("response_nonce",alloc_nonce(nonce,assoc->stateless()));
+ om.set_field("response_nonce",alloc_nonce(nonce));
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) {
+ basic_openid_message& basic_OP::cancel(basic_openid_message& om) {
assert(!return_to.empty());
om.set_field("ns",OIURI_OPENID20);
om.set_field("mode","cancel");
return om;
}
- basic_openid_message& basic_op::error(basic_openid_message& om,
+ basic_openid_message& basic_OP::error(basic_openid_message& om,
const string& error,const string& contact,
const string& reference ) {
assert(!return_to.empty());
om.set_field("ns",OIURI_OPENID20);
om.set_field("mode","error");
om.set_field("error",error);
om.set_field("contact",contact);
om.set_field("reference",reference);
return om;
}
- basic_openid_message& basic_op::setup_needed(
+ basic_openid_message& basic_OP::setup_needed(
basic_openid_message& oum,const basic_openid_message& inm) {
assert(mode==mode_checkid_immediate);
assert(!return_to.empty());
if(openid2) {
oum.set_field("ns",OIURI_OPENID20);
oum.set_field("mode","setup_needed");
@@ -263,13 +263,13 @@ namespace opkele {
util::change_mode_message_proxy(inm,setupmode)
.append_query(get_op_endpoint()));
}
return oum;
}
- basic_openid_message& basic_op::check_authentication(
+ basic_openid_message& basic_OP::check_authentication(
basic_openid_message& oum,
const basic_openid_message& inm) try {
assert(inm.get_field("mode")=="check_authentication");
oum.reset_fields();
oum.set_field("ns",OIURI_OPENID20);
bool o2;
@@ -317,13 +317,13 @@ namespace opkele {
return oum;
}catch(failed_check_authentication& ) {
oum.set_field("is_valid","false");
return oum;
}
- void basic_op::verify_return_to() {
+ void basic_OP::verify_return_to() {
if(realm.find('#')!=string::npos)
throw opkele::bad_realm(OPKELE_CP_ "authentication realm contains URI fragment");
if(!util::uri_matches_realm(return_to,realm))
throw bad_return_to(OPKELE_CP_ "return_to URL doesn't match realm");
}
diff --git a/lib/verify_op.cc b/lib/verify_op.cc
index e7c26b5..0beca2d 100644
--- a/lib/verify_op.cc
+++ b/lib/verify_op.cc
@@ -30,13 +30,13 @@ namespace opkele {
RP_verifier& operator++() { ++seen; return *this; }
RP_verifier& operator++(int) { +seen; return *this; }
};
void verify_op::verify_return_to() {
- basic_op::verify_return_to();
+ basic_OP::verify_return_to();
try {
RP_verifier rpv(return_to);
string drealm = realm;
string::size_type csss = drealm.find("://*.");
if(csss==4 || csss==5)
drealm.replace(csss+3,1,"www");
diff --git a/test/OP.cc b/test/OP.cc
index c919d7f..ce54d92 100644
--- a/test/OP.cc
+++ b/test/OP.cc
@@ -158,13 +158,13 @@ class example_op_t : public opkele::verify_op {
return opkele::assoc_t(new opkele::association(
"", h, T.get(1,1,nc), secret,
strtol(T.get(1,4,nc),0,0),
strtol(T.get(1,3,nc),0,0) ));
}
- string& alloc_nonce(string& nonce,bool stateless) {
+ string& alloc_nonce(string& nonce) {
uuid_t uuid; uuid_generate(uuid);
nonce += opkele::util::encode_base64(uuid,sizeof(uuid));
sqlite3_mem_t<char*>
S = sqlite3_mprintf(
"INSERT INTO nonces"
" (n_once) VALUES (%Q)",