summaryrefslogtreecommitdiffabout
path: root/lib
Unidiff
Diffstat (limited to 'lib') (more/less context) (ignore whitespace changes)
-rw-r--r--lib/basic_op.cc1
-rw-r--r--lib/basic_rp.cc1
-rw-r--r--lib/consumer.cc1
-rw-r--r--lib/server.cc1
4 files changed, 4 insertions, 0 deletions
diff --git a/lib/basic_op.cc b/lib/basic_op.cc
index c247493..fa659ac 100644
--- a/lib/basic_op.cc
+++ b/lib/basic_op.cc
@@ -1,104 +1,105 @@
1#include <time.h> 1#include <time.h>
2#include <cassert> 2#include <cassert>
3#include <openssl/sha.h> 3#include <openssl/sha.h>
4#include <openssl/hmac.h> 4#include <openssl/hmac.h>
5#include <opkele/data.h> 5#include <opkele/data.h>
6#include <opkele/basic_op.h> 6#include <opkele/basic_op.h>
7#include <opkele/exception.h> 7#include <opkele/exception.h>
8#include <opkele/util.h> 8#include <opkele/util.h>
9#include <opkele/util-internal.h>
9#include <opkele/uris.h> 10#include <opkele/uris.h>
10 11
11namespace opkele { 12namespace opkele {
12 13
13 void basic_OP::reset_vars() { 14 void basic_OP::reset_vars() {
14 assoc.reset(); 15 assoc.reset();
15 return_to.clear(); realm.clear(); 16 return_to.clear(); realm.clear();
16 claimed_id.clear(); identity.clear(); 17 claimed_id.clear(); identity.clear();
17 invalidate_handle.clear(); 18 invalidate_handle.clear();
18 } 19 }
19 20
20 bool basic_OP::has_return_to() const { 21 bool basic_OP::has_return_to() const {
21 return !return_to.empty(); 22 return !return_to.empty();
22 } 23 }
23 const string& basic_OP::get_return_to() const { 24 const string& basic_OP::get_return_to() const {
24 if(return_to.empty()) 25 if(return_to.empty())
25 throw no_return_to(OPKELE_CP_ "No return_to URL provided with request"); 26 throw no_return_to(OPKELE_CP_ "No return_to URL provided with request");
26 return return_to; 27 return return_to;
27 } 28 }
28 29
29 const string& basic_OP::get_realm() const { 30 const string& basic_OP::get_realm() const {
30 assert(!realm.empty()); 31 assert(!realm.empty());
31 return realm; 32 return realm;
32 } 33 }
33 34
34 bool basic_OP::has_identity() const { 35 bool basic_OP::has_identity() const {
35 return !identity.empty(); 36 return !identity.empty();
36 } 37 }
37 const string& basic_OP::get_claimed_id() const { 38 const string& basic_OP::get_claimed_id() const {
38 if(claimed_id.empty()) 39 if(claimed_id.empty())
39 throw non_identity(OPKELE_CP_ "attempting to retrieve claimed_id of non-identity related request"); 40 throw non_identity(OPKELE_CP_ "attempting to retrieve claimed_id of non-identity related request");
40 assert(!identity.empty()); 41 assert(!identity.empty());
41 return claimed_id; 42 return claimed_id;
42 } 43 }
43 const string& basic_OP::get_identity() const { 44 const string& basic_OP::get_identity() const {
44 if(identity.empty()) 45 if(identity.empty())
45 throw non_identity(OPKELE_CP_ "attempting to retrieve identity of non-identity related request"); 46 throw non_identity(OPKELE_CP_ "attempting to retrieve identity of non-identity related request");
46 assert(!claimed_id.empty()); 47 assert(!claimed_id.empty());
47 return identity; 48 return identity;
48 } 49 }
49 50
50 bool basic_OP::is_id_select() const { 51 bool basic_OP::is_id_select() const {
51 return identity==IDURI_SELECT20; 52 return identity==IDURI_SELECT20;
52 } 53 }
53 54
54 void basic_OP::select_identity(const string& c,const string& i) { 55 void basic_OP::select_identity(const string& c,const string& i) {
55 claimed_id = c; identity = i; 56 claimed_id = c; identity = i;
56 } 57 }
57 void basic_OP::set_claimed_id(const string& c) { 58 void basic_OP::set_claimed_id(const string& c) {
58 claimed_id = c; 59 claimed_id = c;
59 } 60 }
60 61
61 basic_openid_message& basic_OP::associate( 62 basic_openid_message& basic_OP::associate(
62 basic_openid_message& oum, 63 basic_openid_message& oum,
63 const basic_openid_message& inm) try { 64 const basic_openid_message& inm) try {
64 assert(inm.get_field("mode")=="associate"); 65 assert(inm.get_field("mode")=="associate");
65 util::dh_t dh; 66 util::dh_t dh;
66 util::bignum_t c_pub; 67 util::bignum_t c_pub;
67 unsigned char key_digest[SHA256_DIGEST_LENGTH]; 68 unsigned char key_digest[SHA256_DIGEST_LENGTH];
68 size_t d_len = 0; 69 size_t d_len = 0;
69 string sts = inm.get_field("session_type"); 70 string sts = inm.get_field("session_type");
70 string ats = inm.get_field("assoc_type"); 71 string ats = inm.get_field("assoc_type");
71 if(sts=="DH-SHA1" || sts=="DH-SHA256") { 72 if(sts=="DH-SHA1" || sts=="DH-SHA256") {
72 if(!(dh = DH_new())) 73 if(!(dh = DH_new()))
73 throw exception_openssl(OPKELE_CP_ "failed to DH_new()"); 74 throw exception_openssl(OPKELE_CP_ "failed to DH_new()");
74 c_pub = util::base64_to_bignum(inm.get_field("dh_consumer_public")); 75 c_pub = util::base64_to_bignum(inm.get_field("dh_consumer_public"));
75 try { dh->p = util::base64_to_bignum(inm.get_field("dh_modulus")); 76 try { dh->p = util::base64_to_bignum(inm.get_field("dh_modulus"));
76 }catch(failed_lookup&) { 77 }catch(failed_lookup&) {
77 dh->p = util::dec_to_bignum(data::_default_p); } 78 dh->p = util::dec_to_bignum(data::_default_p); }
78 try { dh->g = util::base64_to_bignum(inm.get_field("dh_gen")); 79 try { dh->g = util::base64_to_bignum(inm.get_field("dh_gen"));
79 }catch(failed_lookup&) { 80 }catch(failed_lookup&) {
80 dh->g = util::dec_to_bignum(data::_default_g); } 81 dh->g = util::dec_to_bignum(data::_default_g); }
81 if(!DH_generate_key(dh)) 82 if(!DH_generate_key(dh))
82 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()"); 83 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()");
83 vector<unsigned char> ck(DH_size(dh)+1); 84 vector<unsigned char> ck(DH_size(dh)+1);
84 unsigned char *ckptr = &(ck.front())+1; 85 unsigned char *ckptr = &(ck.front())+1;
85 int cklen = DH_compute_key(ckptr,c_pub,dh); 86 int cklen = DH_compute_key(ckptr,c_pub,dh);
86 if(cklen<0) 87 if(cklen<0)
87 throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()"); 88 throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()");
88 if(cklen && (*ckptr)&0x80) { 89 if(cklen && (*ckptr)&0x80) {
89 (*(--ckptr)) = 0; ++cklen; } 90 (*(--ckptr)) = 0; ++cklen; }
90 if(sts=="DH-SHA1") { 91 if(sts=="DH-SHA1") {
91 SHA1(ckptr,cklen,key_digest); d_len = SHA_DIGEST_LENGTH; 92 SHA1(ckptr,cklen,key_digest); d_len = SHA_DIGEST_LENGTH;
92 }else if(sts=="DH-SHA256") { 93 }else if(sts=="DH-SHA256") {
93 SHA256(ckptr,cklen,key_digest); d_len = SHA256_DIGEST_LENGTH; 94 SHA256(ckptr,cklen,key_digest); d_len = SHA256_DIGEST_LENGTH;
94 }else 95 }else
95 throw internal_error(OPKELE_CP_ "I thought I knew the session type"); 96 throw internal_error(OPKELE_CP_ "I thought I knew the session type");
96 }else 97 }else
97 throw unsupported(OPKELE_CP_ "Unsupported session_type"); 98 throw unsupported(OPKELE_CP_ "Unsupported session_type");
98 assoc_t a; 99 assoc_t a;
99 if(ats=="HMAC-SHA1") 100 if(ats=="HMAC-SHA1")
100 a = alloc_assoc(ats,SHA_DIGEST_LENGTH,false); 101 a = alloc_assoc(ats,SHA_DIGEST_LENGTH,false);
101 else if(ats=="HMAC-SHA256") 102 else if(ats=="HMAC-SHA256")
102 a = alloc_assoc(ats,SHA256_DIGEST_LENGTH,false); 103 a = alloc_assoc(ats,SHA256_DIGEST_LENGTH,false);
103 else 104 else
104 throw unsupported(OPKELE_CP_ "Unsupported assoc_type"); 105 throw unsupported(OPKELE_CP_ "Unsupported assoc_type");
diff --git a/lib/basic_rp.cc b/lib/basic_rp.cc
index a0ad130..e65d9fb 100644
--- a/lib/basic_rp.cc
+++ b/lib/basic_rp.cc
@@ -1,104 +1,105 @@
1#include <cassert> 1#include <cassert>
2#include <openssl/sha.h> 2#include <openssl/sha.h>
3#include <openssl/hmac.h> 3#include <openssl/hmac.h>
4#include <opkele/basic_rp.h> 4#include <opkele/basic_rp.h>
5#include <opkele/exception.h> 5#include <opkele/exception.h>
6#include <opkele/uris.h> 6#include <opkele/uris.h>
7#include <opkele/data.h> 7#include <opkele/data.h>
8#include <opkele/util.h> 8#include <opkele/util.h>
9#include <opkele/util-internal.h>
9#include <opkele/curl.h> 10#include <opkele/curl.h>
10 11
11namespace opkele { 12namespace opkele {
12 13
13 static void dh_get_secret( 14 static void dh_get_secret(
14 secret_t& secret, const basic_openid_message& om, 15 secret_t& secret, const basic_openid_message& om,
15 const char *exp_assoc, const char *exp_sess, 16 const char *exp_assoc, const char *exp_sess,
16 util::dh_t& dh, 17 util::dh_t& dh,
17 size_t d_len, unsigned char *(*d_fun)(const unsigned char*,size_t,unsigned char*), 18 size_t d_len, unsigned char *(*d_fun)(const unsigned char*,size_t,unsigned char*),
18 size_t exp_s_len) try { 19 size_t exp_s_len) try {
19 if(om.get_field("assoc_type")!=exp_assoc || om.get_field("session_type")!=exp_sess) 20 if(om.get_field("assoc_type")!=exp_assoc || om.get_field("session_type")!=exp_sess)
20 throw bad_input(OPKELE_CP_ "Unexpected associate response"); 21 throw bad_input(OPKELE_CP_ "Unexpected associate response");
21 util::bignum_t s_pub = util::base64_to_bignum(om.get_field("dh_server_public")); 22 util::bignum_t s_pub = util::base64_to_bignum(om.get_field("dh_server_public"));
22 vector<unsigned char> ck(DH_size(dh)+1); 23 vector<unsigned char> ck(DH_size(dh)+1);
23 unsigned char *ckptr = &(ck.front())+1; 24 unsigned char *ckptr = &(ck.front())+1;
24 int cklen = DH_compute_key(ckptr,s_pub,dh); 25 int cklen = DH_compute_key(ckptr,s_pub,dh);
25 if(cklen<0) 26 if(cklen<0)
26 throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()"); 27 throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()");
27 if(cklen && (*ckptr)&0x80) { 28 if(cklen && (*ckptr)&0x80) {
28 (*(--ckptr))=0; ++cklen; } 29 (*(--ckptr))=0; ++cklen; }
29 assert(d_len<=SHA256_DIGEST_LENGTH); 30 assert(d_len<=SHA256_DIGEST_LENGTH);
30 unsigned char key_digest[SHA256_DIGEST_LENGTH]; 31 unsigned char key_digest[SHA256_DIGEST_LENGTH];
31 secret.enxor_from_base64((*d_fun)(ckptr,cklen,key_digest),om.get_field("enc_mac_key")); 32 secret.enxor_from_base64((*d_fun)(ckptr,cklen,key_digest),om.get_field("enc_mac_key"));
32 if(secret.size()!=exp_s_len) 33 if(secret.size()!=exp_s_len)
33 throw bad_input(OPKELE_CP_ "Secret length isn't consistent with association type"); 34 throw bad_input(OPKELE_CP_ "Secret length isn't consistent with association type");
34 }catch(opkele::failed_lookup& ofl) { 35 }catch(opkele::failed_lookup& ofl) {
35 throw bad_input(OPKELE_CP_ "Incoherent response from OP"); 36 throw bad_input(OPKELE_CP_ "Incoherent response from OP");
36 } OPKELE_RETHROW 37 } OPKELE_RETHROW
37 38
38 static void direct_request(basic_openid_message& oum,const basic_openid_message& inm,const string& OP) { 39 static void direct_request(basic_openid_message& oum,const basic_openid_message& inm,const string& OP) {
39 util::curl_pick_t curl = util::curl_pick_t::easy_init(); 40 util::curl_pick_t curl = util::curl_pick_t::easy_init();
40 if(!curl) 41 if(!curl)
41 throw exception_curl(OPKELE_CP_ "failed to initialize curl"); 42 throw exception_curl(OPKELE_CP_ "failed to initialize curl");
42 string request = inm.query_string(); 43 string request = inm.query_string();
43 CURLcode r; 44 CURLcode r;
44 (r=curl.misc_sets()) 45 (r=curl.misc_sets())
45 || (r=curl.easy_setopt(CURLOPT_URL,OP.c_str())) 46 || (r=curl.easy_setopt(CURLOPT_URL,OP.c_str()))
46 || (r=curl.easy_setopt(CURLOPT_POST,1)) 47 || (r=curl.easy_setopt(CURLOPT_POST,1))
47 || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data())) 48 || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data()))
48 || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length())) 49 || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length()))
49 || (r=curl.set_write()); 50 || (r=curl.set_write());
50 if(r) 51 if(r)
51 throw exception_curl(OPKELE_CP_ "failed to set curly options",r); 52 throw exception_curl(OPKELE_CP_ "failed to set curly options",r);
52 if( (r=curl.easy_perform()) ) 53 if( (r=curl.easy_perform()) )
53 throw exception_curl(OPKELE_CP_ "failed to perform curly request",r); 54 throw exception_curl(OPKELE_CP_ "failed to perform curly request",r);
54 oum.from_keyvalues(curl.response); 55 oum.from_keyvalues(curl.response);
55 } 56 }
56 57
57 58
58 assoc_t basic_RP::associate(const string& OP) { 59 assoc_t basic_RP::associate(const string& OP) {
59 util::dh_t dh = DH_new(); 60 util::dh_t dh = DH_new();
60 if(!dh) 61 if(!dh)
61 throw exception_openssl(OPKELE_CP_ "failed to DH_new()"); 62 throw exception_openssl(OPKELE_CP_ "failed to DH_new()");
62 dh->p = util::dec_to_bignum(data::_default_p); 63 dh->p = util::dec_to_bignum(data::_default_p);
63 dh->g = util::dec_to_bignum(data::_default_g); 64 dh->g = util::dec_to_bignum(data::_default_g);
64 if(!DH_generate_key(dh)) 65 if(!DH_generate_key(dh))
65 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()"); 66 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()");
66 openid_message_t req; 67 openid_message_t req;
67 req.set_field("ns",OIURI_OPENID20); 68 req.set_field("ns",OIURI_OPENID20);
68 req.set_field("mode","associate"); 69 req.set_field("mode","associate");
69 req.set_field("dh_modulus",util::bignum_to_base64(dh->p)); 70 req.set_field("dh_modulus",util::bignum_to_base64(dh->p));
70 req.set_field("dh_gen",util::bignum_to_base64(dh->g)); 71 req.set_field("dh_gen",util::bignum_to_base64(dh->g));
71 req.set_field("dh_consumer_public",util::bignum_to_base64(dh->pub_key)); 72 req.set_field("dh_consumer_public",util::bignum_to_base64(dh->pub_key));
72 openid_message_t res; 73 openid_message_t res;
73 req.set_field("assoc_type","HMAC-SHA256"); 74 req.set_field("assoc_type","HMAC-SHA256");
74 req.set_field("session_type","DH-SHA256"); 75 req.set_field("session_type","DH-SHA256");
75 secret_t secret; 76 secret_t secret;
76 int expires_in; 77 int expires_in;
77 try { 78 try {
78 direct_request(res,req,OP); 79 direct_request(res,req,OP);
79 dh_get_secret( secret, res, 80 dh_get_secret( secret, res,
80 "HMAC-SHA256", "DH-SHA256", 81 "HMAC-SHA256", "DH-SHA256",
81 dh, SHA256_DIGEST_LENGTH, SHA256, SHA256_DIGEST_LENGTH ); 82 dh, SHA256_DIGEST_LENGTH, SHA256, SHA256_DIGEST_LENGTH );
82 expires_in = util::string_to_long(res.get_field("expires_in")); 83 expires_in = util::string_to_long(res.get_field("expires_in"));
83 }catch(exception&) { 84 }catch(exception&) {
84 try { 85 try {
85 req.set_field("assoc_type","HMAC-SHA1"); 86 req.set_field("assoc_type","HMAC-SHA1");
86 req.set_field("session_type","DH-SHA1"); 87 req.set_field("session_type","DH-SHA1");
87 direct_request(res,req,OP); 88 direct_request(res,req,OP);
88 dh_get_secret( secret, res, 89 dh_get_secret( secret, res,
89 "HMAC-SHA1", "DH-SHA1", 90 "HMAC-SHA1", "DH-SHA1",
90 dh, SHA_DIGEST_LENGTH, SHA1, SHA_DIGEST_LENGTH ); 91 dh, SHA_DIGEST_LENGTH, SHA1, SHA_DIGEST_LENGTH );
91 expires_in = util::string_to_long(res.get_field("expires_in")); 92 expires_in = util::string_to_long(res.get_field("expires_in"));
92 }catch(bad_input&) { 93 }catch(bad_input&) {
93 throw dumb_RP(OPKELE_CP_ "OP failed to supply an association"); 94 throw dumb_RP(OPKELE_CP_ "OP failed to supply an association");
94 } 95 }
95 } 96 }
96 return store_assoc( 97 return store_assoc(
97 OP, res.get_field("assoc_handle"), 98 OP, res.get_field("assoc_handle"),
98 res.get_field("assoc_type"), secret, 99 res.get_field("assoc_type"), secret,
99 expires_in ); 100 expires_in );
100 } 101 }
101 102
102 basic_openid_message& basic_RP::checkid_( 103 basic_openid_message& basic_RP::checkid_(
103 basic_openid_message& rv, 104 basic_openid_message& rv,
104 mode_t mode, 105 mode_t mode,
diff --git a/lib/consumer.cc b/lib/consumer.cc
index ebda262..801496e 100644
--- a/lib/consumer.cc
+++ b/lib/consumer.cc
@@ -1,100 +1,101 @@
1#include <algorithm> 1#include <algorithm>
2#include <cassert> 2#include <cassert>
3#include <cstring> 3#include <cstring>
4#include <opkele/util.h> 4#include <opkele/util.h>
5#include <opkele/util-internal.h>
5#include <opkele/curl.h> 6#include <opkele/curl.h>
6#include <opkele/exception.h> 7#include <opkele/exception.h>
7#include <opkele/data.h> 8#include <opkele/data.h>
8#include <opkele/consumer.h> 9#include <opkele/consumer.h>
9#include <openssl/sha.h> 10#include <openssl/sha.h>
10#include <openssl/hmac.h> 11#include <openssl/hmac.h>
11#include <iostream> 12#include <iostream>
12 13
13#include "config.h" 14#include "config.h"
14 15
15#include <pcre.h> 16#include <pcre.h>
16 17
17namespace opkele { 18namespace opkele {
18 using namespace std; 19 using namespace std;
19 using util::curl_t; 20 using util::curl_t;
20 using util::curl_pick_t; 21 using util::curl_pick_t;
21 22
22 class pcre_matches_t { 23 class pcre_matches_t {
23 public: 24 public:
24 int *_ov; 25 int *_ov;
25 int _s; 26 int _s;
26 27
27 pcre_matches_t() : _ov(0), _s(0) { } 28 pcre_matches_t() : _ov(0), _s(0) { }
28 pcre_matches_t(int s) : _ov(0), _s(s) { 29 pcre_matches_t(int s) : _ov(0), _s(s) {
29 if(_s&1) ++_s; 30 if(_s&1) ++_s;
30 _s += _s>>1; 31 _s += _s>>1;
31 _ov = new int[_s]; 32 _ov = new int[_s];
32 } 33 }
33 ~pcre_matches_t() throw() { if(_ov) delete[] _ov; } 34 ~pcre_matches_t() throw() { if(_ov) delete[] _ov; }
34 35
35 int begin(int i) const { return _ov[i<<1]; } 36 int begin(int i) const { return _ov[i<<1]; }
36 int end(int i) const { return _ov[(i<<1)+1]; } 37 int end(int i) const { return _ov[(i<<1)+1]; }
37 int length(int i) const { int t=i<<1; return _ov[t+1]-_ov[t]; } 38 int length(int i) const { int t=i<<1; return _ov[t+1]-_ov[t]; }
38 }; 39 };
39 40
40 class pcre_t { 41 class pcre_t {
41 public: 42 public:
42 pcre *_p; 43 pcre *_p;
43 44
44 pcre_t() : _p(0) { } 45 pcre_t() : _p(0) { }
45 pcre_t(pcre *p) : _p(p) { } 46 pcre_t(pcre *p) : _p(p) { }
46 pcre_t(const char *re,int opts) : _p(0) { 47 pcre_t(const char *re,int opts) : _p(0) {
47 static const char *errptr; static int erroffset; 48 static const char *errptr; static int erroffset;
48 _p = pcre_compile(re,opts,&errptr,&erroffset,NULL); 49 _p = pcre_compile(re,opts,&errptr,&erroffset,NULL);
49 if(!_p) 50 if(!_p)
50 throw internal_error(OPKELE_CP_ string("Failed to compile regexp: ")+errptr); 51 throw internal_error(OPKELE_CP_ string("Failed to compile regexp: ")+errptr);
51 } 52 }
52 ~pcre_t() throw() { if(_p) (*pcre_free)(_p); } 53 ~pcre_t() throw() { if(_p) (*pcre_free)(_p); }
53 54
54 pcre_t& operator=(pcre *p) { if(_p) (*pcre_free)(_p); _p=p; return *this; } 55 pcre_t& operator=(pcre *p) { if(_p) (*pcre_free)(_p); _p=p; return *this; }
55 56
56 operator const pcre*(void) const { return _p; } 57 operator const pcre*(void) const { return _p; }
57 operator pcre*(void) { return _p; } 58 operator pcre*(void) { return _p; }
58 59
59 int exec(const string& s,pcre_matches_t& m) { 60 int exec(const string& s,pcre_matches_t& m) {
60 if(!_p) 61 if(!_p)
61 throw internal_error(OPKELE_CP_ "Trying to execute absent regexp"); 62 throw internal_error(OPKELE_CP_ "Trying to execute absent regexp");
62 return pcre_exec(_p,NULL,s.c_str(),s.length(),0,0,m._ov,m._s); 63 return pcre_exec(_p,NULL,s.c_str(),s.length(),0,0,m._ov,m._s);
63 } 64 }
64 }; 65 };
65 66
66 assoc_t consumer_t::associate(const string& server) { 67 assoc_t consumer_t::associate(const string& server) {
67 util::dh_t dh = DH_new(); 68 util::dh_t dh = DH_new();
68 if(!dh) 69 if(!dh)
69 throw exception_openssl(OPKELE_CP_ "failed to DH_new()"); 70 throw exception_openssl(OPKELE_CP_ "failed to DH_new()");
70 dh->p = util::dec_to_bignum(data::_default_p); 71 dh->p = util::dec_to_bignum(data::_default_p);
71 dh->g = util::dec_to_bignum(data::_default_g); 72 dh->g = util::dec_to_bignum(data::_default_g);
72 if(!DH_generate_key(dh)) 73 if(!DH_generate_key(dh))
73 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()"); 74 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()");
74 string request = 75 string request =
75 "openid.mode=associate" 76 "openid.mode=associate"
76 "&openid.assoc_type=HMAC-SHA1" 77 "&openid.assoc_type=HMAC-SHA1"
77 "&openid.session_type=DH-SHA1" 78 "&openid.session_type=DH-SHA1"
78 "&openid.dh_consumer_public="; 79 "&openid.dh_consumer_public=";
79 request += util::url_encode(util::bignum_to_base64(dh->pub_key)); 80 request += util::url_encode(util::bignum_to_base64(dh->pub_key));
80 curl_pick_t curl = curl_pick_t::easy_init(); 81 curl_pick_t curl = curl_pick_t::easy_init();
81 if(!curl) 82 if(!curl)
82 throw exception_curl(OPKELE_CP_ "failed to initialize curl"); 83 throw exception_curl(OPKELE_CP_ "failed to initialize curl");
83 CURLcode r; 84 CURLcode r;
84 (r=curl.misc_sets()) 85 (r=curl.misc_sets())
85 || (r=curl.easy_setopt(CURLOPT_URL,server.c_str())) 86 || (r=curl.easy_setopt(CURLOPT_URL,server.c_str()))
86 || (r=curl.easy_setopt(CURLOPT_POST,1)) 87 || (r=curl.easy_setopt(CURLOPT_POST,1))
87 || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data())) 88 || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data()))
88 || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length())) 89 || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length()))
89 || (r=curl.set_write()) 90 || (r=curl.set_write())
90 ; 91 ;
91 if(r) 92 if(r)
92 throw exception_curl(OPKELE_CP_ "failed to set curly options",r); 93 throw exception_curl(OPKELE_CP_ "failed to set curly options",r);
93 if( (r=curl.easy_perform()) ) 94 if( (r=curl.easy_perform()) )
94 throw exception_curl(OPKELE_CP_ "failed to perform curly request",r); 95 throw exception_curl(OPKELE_CP_ "failed to perform curly request",r);
95 params_t p; p.parse_keyvalues(curl.response); 96 params_t p; p.parse_keyvalues(curl.response);
96 if(p.has_param("assoc_type") && p.get_param("assoc_type")!="HMAC-SHA1") 97 if(p.has_param("assoc_type") && p.get_param("assoc_type")!="HMAC-SHA1")
97 throw bad_input(OPKELE_CP_ "unsupported assoc_type"); 98 throw bad_input(OPKELE_CP_ "unsupported assoc_type");
98 string st; 99 string st;
99 if(p.has_param("session_type")) st = p.get_param("session_type"); 100 if(p.has_param("session_type")) st = p.get_param("session_type");
100 if((!st.empty()) && st!="DH-SHA1") 101 if((!st.empty()) && st!="DH-SHA1")
diff --git a/lib/server.cc b/lib/server.cc
index 776f1ae..0dea1eb 100644
--- a/lib/server.cc
+++ b/lib/server.cc
@@ -1,101 +1,102 @@
1#include <cstring> 1#include <cstring>
2#include <vector> 2#include <vector>
3#include <openssl/sha.h> 3#include <openssl/sha.h>
4#include <openssl/hmac.h> 4#include <openssl/hmac.h>
5#include <opkele/util.h> 5#include <opkele/util.h>
6#include <opkele/util-internal.h>
6#include <opkele/exception.h> 7#include <opkele/exception.h>
7#include <opkele/server.h> 8#include <opkele/server.h>
8#include <opkele/data.h> 9#include <opkele/data.h>
9 10
10namespace opkele { 11namespace opkele {
11 using namespace std; 12 using namespace std;
12 13
13 void server_t::associate(const params_t& pin,params_t& pout) { 14 void server_t::associate(const params_t& pin,params_t& pout) {
14 util::dh_t dh; 15 util::dh_t dh;
15 util::bignum_t c_pub; 16 util::bignum_t c_pub;
16 unsigned char key_sha1[SHA_DIGEST_LENGTH]; 17 unsigned char key_sha1[SHA_DIGEST_LENGTH];
17 enum { 18 enum {
18 sess_cleartext, 19 sess_cleartext,
19 sess_dh_sha1 20 sess_dh_sha1
20 } st = sess_cleartext; 21 } st = sess_cleartext;
21 if( 22 if(
22 pin.has_param("openid.session_type") 23 pin.has_param("openid.session_type")
23 && pin.get_param("openid.session_type")=="DH-SHA1" ) { 24 && pin.get_param("openid.session_type")=="DH-SHA1" ) {
24 /* TODO: fallback to cleartext in case of exceptions here? */ 25 /* TODO: fallback to cleartext in case of exceptions here? */
25 if(!(dh = DH_new())) 26 if(!(dh = DH_new()))
26 throw exception_openssl(OPKELE_CP_ "failed to DH_new()"); 27 throw exception_openssl(OPKELE_CP_ "failed to DH_new()");
27 c_pub = util::base64_to_bignum(pin.get_param("openid.dh_consumer_public")); 28 c_pub = util::base64_to_bignum(pin.get_param("openid.dh_consumer_public"));
28 if(pin.has_param("openid.dh_modulus")) 29 if(pin.has_param("openid.dh_modulus"))
29 dh->p = util::base64_to_bignum(pin.get_param("openid.dh_modulus")); 30 dh->p = util::base64_to_bignum(pin.get_param("openid.dh_modulus"));
30 else 31 else
31 dh->p = util::dec_to_bignum(data::_default_p); 32 dh->p = util::dec_to_bignum(data::_default_p);
32 if(pin.has_param("openid.dh_gen")) 33 if(pin.has_param("openid.dh_gen"))
33 dh->g = util::base64_to_bignum(pin.get_param("openid.dh_gen")); 34 dh->g = util::base64_to_bignum(pin.get_param("openid.dh_gen"));
34 else 35 else
35 dh->g = util::dec_to_bignum(data::_default_g); 36 dh->g = util::dec_to_bignum(data::_default_g);
36 if(!DH_generate_key(dh)) 37 if(!DH_generate_key(dh))
37 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()"); 38 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()");
38 vector<unsigned char> ck(DH_size(dh)+1); 39 vector<unsigned char> ck(DH_size(dh)+1);
39 unsigned char *ckptr = &(ck.front())+1; 40 unsigned char *ckptr = &(ck.front())+1;
40 int cklen = DH_compute_key(ckptr,c_pub,dh); 41 int cklen = DH_compute_key(ckptr,c_pub,dh);
41 if(cklen<0) 42 if(cklen<0)
42 throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()"); 43 throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()");
43 if(cklen && (*ckptr)&0x80) { 44 if(cklen && (*ckptr)&0x80) {
44 (*(--ckptr)) = 0; ++cklen; 45 (*(--ckptr)) = 0; ++cklen;
45 } 46 }
46 SHA1(ckptr,cklen,key_sha1); 47 SHA1(ckptr,cklen,key_sha1);
47 st = sess_dh_sha1; 48 st = sess_dh_sha1;
48 } 49 }
49 assoc_t assoc = alloc_assoc(mode_associate); 50 assoc_t assoc = alloc_assoc(mode_associate);
50 time_t now = time(0); 51 time_t now = time(0);
51 pout.clear(); 52 pout.clear();
52 pout["assoc_type"] = assoc->assoc_type(); 53 pout["assoc_type"] = assoc->assoc_type();
53 pout["assoc_handle"] = assoc->handle(); 54 pout["assoc_handle"] = assoc->handle();
54 /* TODO: eventually remove deprecated stuff */ 55 /* TODO: eventually remove deprecated stuff */
55 pout["issued"] = util::time_to_w3c(now); 56 pout["issued"] = util::time_to_w3c(now);
56 pout["expiry"] = util::time_to_w3c(now+assoc->expires_in()); 57 pout["expiry"] = util::time_to_w3c(now+assoc->expires_in());
57 pout["expires_in"] = util::long_to_string(assoc->expires_in()); 58 pout["expires_in"] = util::long_to_string(assoc->expires_in());
58 secret_t secret = assoc->secret(); 59 secret_t secret = assoc->secret();
59 switch(st) { 60 switch(st) {
60 case sess_dh_sha1: 61 case sess_dh_sha1:
61 pout["session_type"] = "DH-SHA1"; 62 pout["session_type"] = "DH-SHA1";
62 pout["dh_server_public"] = util::bignum_to_base64(dh->pub_key); 63 pout["dh_server_public"] = util::bignum_to_base64(dh->pub_key);
63 secret.enxor_to_base64(key_sha1,pout["enc_mac_key"]); 64 secret.enxor_to_base64(key_sha1,pout["enc_mac_key"]);
64 break; 65 break;
65 default: 66 default:
66 secret.to_base64(pout["mac_key"]); 67 secret.to_base64(pout["mac_key"]);
67 break; 68 break;
68 } 69 }
69 } 70 }
70 71
71 void server_t::checkid_immediate(const params_t& pin,string& return_to,params_t& pout,extension_t *ext) { 72 void server_t::checkid_immediate(const params_t& pin,string& return_to,params_t& pout,extension_t *ext) {
72 checkid_(mode_checkid_immediate,pin,return_to,pout,ext); 73 checkid_(mode_checkid_immediate,pin,return_to,pout,ext);
73 } 74 }
74 75
75 void server_t::checkid_setup(const params_t& pin,string& return_to,params_t& pout,extension_t *ext) { 76 void server_t::checkid_setup(const params_t& pin,string& return_to,params_t& pout,extension_t *ext) {
76 checkid_(mode_checkid_setup,pin,return_to,pout,ext); 77 checkid_(mode_checkid_setup,pin,return_to,pout,ext);
77 } 78 }
78 79
79 void server_t::checkid_(mode_t mode,const params_t& pin,string& return_to,params_t& pout,extension_t *ext) { 80 void server_t::checkid_(mode_t mode,const params_t& pin,string& return_to,params_t& pout,extension_t *ext) {
80 if(mode!=mode_checkid_immediate && mode!=mode_checkid_setup) 81 if(mode!=mode_checkid_immediate && mode!=mode_checkid_setup)
81 throw bad_input(OPKELE_CP_ "invalid checkid_* mode"); 82 throw bad_input(OPKELE_CP_ "invalid checkid_* mode");
82 pout.clear(); 83 pout.clear();
83 assoc_t assoc; 84 assoc_t assoc;
84 try { 85 try {
85 assoc = retrieve_assoc(pin.get_param("openid.assoc_handle")); 86 assoc = retrieve_assoc(pin.get_param("openid.assoc_handle"));
86 }catch(failed_lookup& fl) { 87 }catch(failed_lookup& fl) {
87 // no handle specified or no valid handle found, going dumb 88 // no handle specified or no valid handle found, going dumb
88 assoc = alloc_assoc(mode_checkid_setup); 89 assoc = alloc_assoc(mode_checkid_setup);
89 if(pin.has_param("openid.assoc_handle")) 90 if(pin.has_param("openid.assoc_handle"))
90 pout["invalidate_handle"]=pin.get_param("openid.assoc_handle"); 91 pout["invalidate_handle"]=pin.get_param("openid.assoc_handle");
91 } 92 }
92 string trust_root; 93 string trust_root;
93 try { 94 try {
94 trust_root = pin.get_param("openid.trust_root"); 95 trust_root = pin.get_param("openid.trust_root");
95 }catch(failed_lookup& fl) { } 96 }catch(failed_lookup& fl) { }
96 string identity = pin.get_param("openid.identity"); 97 string identity = pin.get_param("openid.identity");
97 return_to = pin.get_param("openid.return_to"); 98 return_to = pin.get_param("openid.return_to");
98 validate(*assoc,pin,identity,trust_root); 99 validate(*assoc,pin,identity,trust_root);
99 pout["mode"] = "id_res"; 100 pout["mode"] = "id_res";
100 pout["assoc_handle"] = assoc->handle(); 101 pout["assoc_handle"] = assoc->handle();
101 if(pin.has_param("openid.assoc_handle") && assoc->stateless()) 102 if(pin.has_param("openid.assoc_handle") && assoc->stateless())