diff options
-rw-r--r-- | classes/Consumer.php | 23 | ||||
-rw-r--r-- | classes/Nonce.php | 25 | ||||
-rw-r--r-- | classes/Subscription.php | 1 | ||||
-rw-r--r-- | classes/Token.php | 26 | ||||
-rw-r--r-- | classes/stoica.ini | 36 | ||||
-rw-r--r-- | db/stoica.sql | 36 | ||||
-rw-r--r-- | lib/oauthstore.php | 111 | ||||
-rw-r--r-- | lib/util.php | 32 |
8 files changed, 290 insertions, 0 deletions
diff --git a/classes/Consumer.php b/classes/Consumer.php new file mode 100644 index 000000000..6f4513f33 --- /dev/null +++ b/classes/Consumer.php @@ -0,0 +1,23 @@ +<?php +/** + * Table Definition for consumer + */ +require_once 'DB/DataObject.php'; + +class Consumer extends DB_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'consumer'; // table name + public $consumer_key; // varchar(255) primary_key not_null + public $seed; // char(32) not_null + public $created; // datetime() not_null + public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('Consumer',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/classes/Nonce.php b/classes/Nonce.php new file mode 100644 index 000000000..987e8d1e8 --- /dev/null +++ b/classes/Nonce.php @@ -0,0 +1,25 @@ +<?php +/** + * Table Definition for nonce + */ +require_once 'DB/DataObject.php'; + +class Nonce extends DB_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'nonce'; // table name + public $consumer_key; // varchar(255) primary_key not_null + public $tok; // char(32) primary_key not_null + public $nonce; // char(32) primary_key not_null + public $ts; // datetime() not_null + public $created; // datetime() not_null + public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('Nonce',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/classes/Subscription.php b/classes/Subscription.php index 42a3916c4..2a1037d2b 100644 --- a/classes/Subscription.php +++ b/classes/Subscription.php @@ -33,6 +33,7 @@ class Subscription extends DB_DataObject public $subscriber; // int(4) primary_key not_null public $subscribed; // int(4) primary_key not_null public $token; // varchar(255) + public $secret; // varchar(255) public $created; // datetime() not_null public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP diff --git a/classes/Token.php b/classes/Token.php new file mode 100644 index 000000000..a91b19f8e --- /dev/null +++ b/classes/Token.php @@ -0,0 +1,26 @@ +<?php +/** + * Table Definition for token + */ +require_once 'DB/DataObject.php'; + +class Token extends DB_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'token'; // table name + public $consumer_key; // varchar(255) primary_key not_null + public $tok; // char(32) primary_key not_null + public $secret; // char(32) not_null + public $type; // tinyint(1) not_null + public $state; // tinyint(1) + public $created; // datetime() not_null + public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP + + /* Static get */ + function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('Token',$k,$v); } + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE +} diff --git a/classes/stoica.ini b/classes/stoica.ini index 1cb6f9e05..38ecfe84b 100644 --- a/classes/stoica.ini +++ b/classes/stoica.ini @@ -16,6 +16,28 @@ width = K height = K url = U +[consumer] +consumer_key = 130 +seed = 130 +created = 142 +modified = 384 + +[consumer__keys] +consumer_key = K + +[nonce] +consumer_key = 130 +tok = 130 +nonce = 130 +ts = 142 +created = 142 +modified = 384 + +[nonce__keys] +consumer_key = K +tok = K +nonce = K + [notice] id = 129 profile_id = 129 @@ -58,6 +80,7 @@ uri = U subscriber = 129 subscribed = 129 token = 2 +secret = 2 created = 142 modified = 384 @@ -65,6 +88,19 @@ modified = 384 subscriber = K subscribed = K +[token] +consumer_key = 130 +tok = 130 +secret = 130 +type = 145 +state = 17 +created = 142 +modified = 384 + +[token__keys] +consumer_key = K +tok = K + [user] id = 129 nickname = 2 diff --git a/db/stoica.sql b/db/stoica.sql index 6a460b350..97f56bd15 100644 --- a/db/stoica.sql +++ b/db/stoica.sql @@ -76,4 +76,40 @@ create table notice ( modified timestamp comment 'date this record was modified', index notice_profile_id_idx (profile_id) +); + +/* tables for OAuth */ + +create table consumer ( + consumer_key varchar(255) primary key comment 'unique identifier, root URL', + seed char(32) not null comment 'seed for new tokens by this consumer', + + created datetime not null comment 'date this record was created', + modified timestamp comment 'date this record was modified' +); + +create table token ( + consumer_key varchar(255) not null comment 'unique identifier, root URL' references consumer (consumer_key), + tok char(32) not null comment 'identifying value', + secret char(32) not null comment 'secret value', + type tinyint not null default 0 comment 'request or access', + state tinyint default 0 comment 'for requests; 0 = initial, 1 = authorized, 2 = used', + + created datetime not null comment 'date this record was created', + modified timestamp comment 'date this record was modified', + + constraint primary key (consumer_key, tok) +); + +create table nonce ( + consumer_key varchar(255) not null comment 'unique identifier, root URL', + tok char(32) not null comment 'identifying value', + nonce char(32) not null comment 'nonce', + ts datetime not null comment 'timestamp sent', + + created datetime not null comment 'date this record was created', + modified timestamp comment 'date this record was modified', + + constraint primary key (consumer_key, tok, nonce), + constraint foreign key (consumer_key, tok) references token (consumer_key, tok) );
\ No newline at end of file diff --git a/lib/oauthstore.php b/lib/oauthstore.php new file mode 100644 index 000000000..a622647b7 --- /dev/null +++ b/lib/oauthstore.php @@ -0,0 +1,111 @@ +<?php +/* + * Laconica - a distributed open-source microblogging tool + * Copyright (C) 2008, Controlez-Vous, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +if (!defined('LACONICA')) { exit(1); } + +require_once(INSTALLDIR.'/lib/omb.php'); + +class LaconicaOAuthDataStore extends OAuthDataStore { + + # We just keep a record of who's contacted us + + function lookup_consumer($consumer_key) { + $con = new Consumer('key', $consumer_key); + if (!$con) { + $con = new Consumer(); + $con->consumer_key = $consumer_key; + $con->seed = common_good_rand(16); + $con->created = DB_DataObject_Cast::dateTime(); + if (!$con->insert()) { + return NULL; + } + } + return new OAuthConsumer($con->consumer_key, ''); + } + + function lookup_token($consumer, $token_type, $token) { + $t = new Token(); + $t->consumer_key = $consumer->consumer_key; + $t->tok = $token; + $t->type = ($token_type == 'access') ? 1 : 0; + if ($t->find(true)) { + return new OAuthToken($t->tok, $t->secret); + } else { + return NULL; + } + } + + function lookup_nonce($consumer, $token, $nonce, $timestamp) { + $n = new Nonce(); + $n->consumer_key = $consumer->consumer_key; + $n->tok = $token; + $n->nonce = $nonce; + if ($n->find(TRUE)) { + return TRUE; + } else { + $n->timestamp = $timestamp; + $n->created = DB_DataObject_Cast::dateTime(); + $n->insert(); + return FALSE; + } + } + + function fetch_request_token($consumer) { + $t = new Token(); + $t->consumer_key = $consumer->consumer_key; + $t->tok = common_good_rand(16); + $t->secret = common_good_rand(16); + $t->type = 0; # request + $t->state = 0; + $t->created = DB_DataObject_Cast::dateTime(); + if (!$t->insert()) { + return NULL; + } else { + return new OAuthToken($t->tok, $t->secret); + } + } + + function fetch_access_token($token, $consumer) { + $rt = new Token(); + $rt->consumer_key = $consumer->consumer_key; + $rt->tok = $token; + if ($rt->find(TRUE) && $rt->state == 1) { + $at = new Token(); + $at->consumer_key = $consumer->consumer_key; + $at->tok = common_good_rand(16); + $at->secret = common_good_rand(16); + $at->type = 1; # access + $at->created = DB_DataObject_Cast::dateTime(); + if (!$at->insert()) { + return NULL; + } else { + # burn the old one + $orig_rt = clone($rt); + $rt->state = 2; # used + if (!$rt->update($orig_rt)) { + return NULL; + } else { + return new OAuthToken($at->tok, $at->secret); + } + } + } else { + return NULL; + } + } +} diff --git a/lib/util.php b/lib/util.php index 31a2cbd4f..52f25c9d3 100644 --- a/lib/util.php +++ b/lib/util.php @@ -447,6 +447,38 @@ function common_root_url() { return "http://".$config['site']['server'].'/'.$pathpart; } +# returns $bytes bytes of random data as a hexadecimal string +# "good" here is a goal and not a guarantee + +function common_good_rand($bytes) { + # XXX: use random.org...? + if (file_exists('/dev/urandom')) { + return common_urandom($bytes); + } else { # FIXME: this is probably not good enough + return common_mtrand($bytes); + } +} + +function common_urandom($bytes) { + $h = fopen('/dev/urandom', 'rb'); + # should not block + $src = fread($h, $bytes); + fclose($h); + $enc = ''; + for ($i = 0; $i < $bytes; $i++) { + $enc .= sprintf("%02x", (ord($src[$i]))); + } + return $enc; +} + +function common_mtrand($bytes) { + $enc = ''; + for ($i = 0; $i < $bytes; $i++) { + $enc .= sprintf("%02x", mt_rand(0, 255)); + } + return $enc; +} + // XXX: set up gettext function _t($str) { |