mirror of
https://github.com/TracksApp/tracks.git
synced 2025-12-24 03:00:12 +01:00
Upgraded to open_id_authentication plugin at 00d8bc7f97 and unpacked ruby-openid gem version 2.1.2.
This commit is contained in:
parent
6149900e0c
commit
e92dae2ffc
227 changed files with 30857 additions and 669 deletions
271
vendor/gems/ruby-openid-2.1.2/lib/openid/store/filesystem.rb
vendored
Normal file
271
vendor/gems/ruby-openid-2.1.2/lib/openid/store/filesystem.rb
vendored
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
require 'fileutils'
|
||||
require 'pathname'
|
||||
require 'tempfile'
|
||||
|
||||
require 'openid/util'
|
||||
require 'openid/store/interface'
|
||||
require 'openid/association'
|
||||
|
||||
module OpenID
|
||||
module Store
|
||||
class Filesystem < Interface
|
||||
@@FILENAME_ALLOWED = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-".split("")
|
||||
|
||||
# Create a Filesystem store instance, putting all data in +directory+.
|
||||
def initialize(directory)
|
||||
p_dir = Pathname.new(directory)
|
||||
@nonce_dir = p_dir.join('nonces')
|
||||
@association_dir = p_dir.join('associations')
|
||||
@temp_dir = p_dir.join('temp')
|
||||
|
||||
self.ensure_dir(@nonce_dir)
|
||||
self.ensure_dir(@association_dir)
|
||||
self.ensure_dir(@temp_dir)
|
||||
end
|
||||
|
||||
# Create a unique filename for a given server url and handle. The
|
||||
# filename that is returned will contain the domain name from the
|
||||
# server URL for ease of human inspection of the data dir.
|
||||
def get_association_filename(server_url, handle)
|
||||
unless server_url.index('://')
|
||||
raise ArgumentError, "Bad server URL: #{server_url}"
|
||||
end
|
||||
|
||||
proto, rest = server_url.split('://', 2)
|
||||
domain = filename_escape(rest.split('/',2)[0])
|
||||
url_hash = safe64(server_url)
|
||||
if handle
|
||||
handle_hash = safe64(handle)
|
||||
else
|
||||
handle_hash = ''
|
||||
end
|
||||
filename = [proto,domain,url_hash,handle_hash].join('-')
|
||||
@association_dir.join(filename)
|
||||
end
|
||||
|
||||
# Store an association in the assoc directory
|
||||
def store_association(server_url, association)
|
||||
assoc_s = association.serialize
|
||||
filename = get_association_filename(server_url, association.handle)
|
||||
f, tmp = mktemp
|
||||
|
||||
begin
|
||||
begin
|
||||
f.write(assoc_s)
|
||||
f.fsync
|
||||
ensure
|
||||
f.close
|
||||
end
|
||||
|
||||
begin
|
||||
File.rename(tmp, filename)
|
||||
rescue Errno::EEXIST
|
||||
|
||||
begin
|
||||
File.unlink(filename)
|
||||
rescue Errno::ENOENT
|
||||
# do nothing
|
||||
end
|
||||
|
||||
File.rename(tmp, filename)
|
||||
end
|
||||
|
||||
rescue
|
||||
self.remove_if_present(tmp)
|
||||
raise
|
||||
end
|
||||
end
|
||||
|
||||
# Retrieve an association
|
||||
def get_association(server_url, handle=nil)
|
||||
# the filename with empty handle is the prefix for the associations
|
||||
# for a given server url
|
||||
filename = get_association_filename(server_url, handle)
|
||||
if handle
|
||||
return _get_association(filename)
|
||||
end
|
||||
assoc_filenames = Dir.glob(filename.to_s + '*')
|
||||
|
||||
assocs = assoc_filenames.collect do |f|
|
||||
_get_association(f)
|
||||
end
|
||||
|
||||
assocs = assocs.find_all { |a| not a.nil? }
|
||||
assocs = assocs.sort_by { |a| a.issued }
|
||||
|
||||
return nil if assocs.empty?
|
||||
return assocs[-1]
|
||||
end
|
||||
|
||||
def _get_association(filename)
|
||||
begin
|
||||
assoc_file = File.open(filename, "r")
|
||||
rescue Errno::ENOENT
|
||||
return nil
|
||||
else
|
||||
begin
|
||||
assoc_s = assoc_file.read
|
||||
ensure
|
||||
assoc_file.close
|
||||
end
|
||||
|
||||
begin
|
||||
association = Association.deserialize(assoc_s)
|
||||
rescue
|
||||
self.remove_if_present(filename)
|
||||
return nil
|
||||
end
|
||||
|
||||
# clean up expired associations
|
||||
if association.expires_in == 0
|
||||
self.remove_if_present(filename)
|
||||
return nil
|
||||
else
|
||||
return association
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Remove an association if it exists, otherwise do nothing.
|
||||
def remove_association(server_url, handle)
|
||||
assoc = get_association(server_url, handle)
|
||||
|
||||
if assoc.nil?
|
||||
return false
|
||||
else
|
||||
filename = get_association_filename(server_url, handle)
|
||||
return self.remove_if_present(filename)
|
||||
end
|
||||
end
|
||||
|
||||
# Return whether the nonce is valid
|
||||
def use_nonce(server_url, timestamp, salt)
|
||||
return false if (timestamp - Time.now.to_i).abs > Nonce.skew
|
||||
|
||||
if server_url and !server_url.empty?
|
||||
proto, rest = server_url.split('://',2)
|
||||
else
|
||||
proto, rest = '',''
|
||||
end
|
||||
raise "Bad server URL" unless proto && rest
|
||||
|
||||
domain = filename_escape(rest.split('/',2)[0])
|
||||
url_hash = safe64(server_url)
|
||||
salt_hash = safe64(salt)
|
||||
|
||||
nonce_fn = '%08x-%s-%s-%s-%s'%[timestamp, proto, domain, url_hash, salt_hash]
|
||||
|
||||
filename = @nonce_dir.join(nonce_fn)
|
||||
|
||||
begin
|
||||
fd = File.new(filename, File::CREAT | File::EXCL | File::WRONLY, 0200)
|
||||
fd.close
|
||||
return true
|
||||
rescue Errno::EEXIST
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Remove expired entries from the database. This is potentially expensive,
|
||||
# so only run when it is acceptable to take time.
|
||||
def cleanup
|
||||
cleanup_associations
|
||||
cleanup_nonces
|
||||
end
|
||||
|
||||
def cleanup_associations
|
||||
association_filenames = Dir[@association_dir.join("*").to_s]
|
||||
count = 0
|
||||
association_filenames.each do |af|
|
||||
begin
|
||||
f = File.open(af, 'r')
|
||||
rescue Errno::ENOENT
|
||||
next
|
||||
else
|
||||
begin
|
||||
assoc_s = f.read
|
||||
ensure
|
||||
f.close
|
||||
end
|
||||
begin
|
||||
association = OpenID::Association.deserialize(assoc_s)
|
||||
rescue StandardError
|
||||
self.remove_if_present(af)
|
||||
next
|
||||
else
|
||||
if association.expires_in == 0
|
||||
self.remove_if_present(af)
|
||||
count += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
def cleanup_nonces
|
||||
nonces = Dir[@nonce_dir.join("*").to_s]
|
||||
now = Time.now.to_i
|
||||
|
||||
count = 0
|
||||
nonces.each do |filename|
|
||||
nonce = filename.split('/')[-1]
|
||||
timestamp = nonce.split('-', 2)[0].to_i(16)
|
||||
nonce_age = (timestamp - now).abs
|
||||
if nonce_age > Nonce.skew
|
||||
self.remove_if_present(filename)
|
||||
count += 1
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Create a temporary file and return the File object and filename.
|
||||
def mktemp
|
||||
f = Tempfile.new('tmp', @temp_dir)
|
||||
[f, f.path]
|
||||
end
|
||||
|
||||
# create a safe filename from a url
|
||||
def filename_escape(s)
|
||||
s = '' if s.nil?
|
||||
filename_chunks = []
|
||||
s.split('').each do |c|
|
||||
if @@FILENAME_ALLOWED.index(c)
|
||||
filename_chunks << c
|
||||
else
|
||||
filename_chunks << sprintf("_%02X", c[0])
|
||||
end
|
||||
end
|
||||
filename_chunks.join("")
|
||||
end
|
||||
|
||||
def safe64(s)
|
||||
s = OpenID::CryptUtil.sha1(s)
|
||||
s = OpenID::Util.to_base64(s)
|
||||
s.gsub!('+', '_')
|
||||
s.gsub!('/', '.')
|
||||
s.gsub!('=', '')
|
||||
return s
|
||||
end
|
||||
|
||||
# remove file if present in filesystem
|
||||
def remove_if_present(filename)
|
||||
begin
|
||||
File.unlink(filename)
|
||||
rescue Errno::ENOENT
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
# ensure that a path exists
|
||||
def ensure_dir(dir_name)
|
||||
FileUtils::mkdir_p(dir_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
75
vendor/gems/ruby-openid-2.1.2/lib/openid/store/interface.rb
vendored
Normal file
75
vendor/gems/ruby-openid-2.1.2/lib/openid/store/interface.rb
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
require 'openid/util'
|
||||
|
||||
module OpenID
|
||||
|
||||
# Stores for Associations and nonces. Used by both the Consumer and
|
||||
# the Server. If you have a database abstraction layer or other
|
||||
# state storage in your application or framework already, you can
|
||||
# implement the store interface.
|
||||
module Store
|
||||
# Abstract Store
|
||||
# Changes in 2.0:
|
||||
# * removed store_nonce, get_auth_key, is_dumb
|
||||
# * changed use_nonce to support one-way nonces
|
||||
# * added cleanup_nonces, cleanup_associations, cleanup
|
||||
class Interface < Object
|
||||
|
||||
# Put a Association object into storage.
|
||||
# When implementing a store, don't assume that there are any limitations
|
||||
# on the character set of the server_url. In particular, expect to see
|
||||
# unescaped non-url-safe characters in the server_url field.
|
||||
def store_association(server_url, association)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Returns a Association object from storage that matches
|
||||
# the server_url. Returns nil if no such association is found or if
|
||||
# the one matching association is expired. (Is allowed to GC expired
|
||||
# associations when found.)
|
||||
def get_association(server_url, handle=nil)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# If there is a matching association, remove it from the store and
|
||||
# return true, otherwise return false.
|
||||
def remove_association(server_url, handle)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Return true if the nonce has not been used before, and store it
|
||||
# for a while to make sure someone doesn't try to use the same value
|
||||
# again. Return false if the nonce has already been used or if the
|
||||
# timestamp is not current.
|
||||
# You can use OpenID::Store::Nonce::SKEW for your timestamp window.
|
||||
# server_url: URL of the server from which the nonce originated
|
||||
# timestamp: time the nonce was created in seconds since unix epoch
|
||||
# salt: A random string that makes two nonces issued by a server in
|
||||
# the same second unique
|
||||
def use_nonce(server_url, timestamp, salt)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Remove expired nonces from the store
|
||||
# Discards any nonce that is old enough that it wouldn't pass use_nonce
|
||||
# Not called during normal library operation, this method is for store
|
||||
# admins to keep their storage from filling up with expired data
|
||||
def cleanup_nonces
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Remove expired associations from the store
|
||||
# Not called during normal library operation, this method is for store
|
||||
# admins to keep their storage from filling up with expired data
|
||||
def cleanup_associations
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Remove expired nonces and associations from the store
|
||||
# Not called during normal library operation, this method is for store
|
||||
# admins to keep their storage from filling up with expired data
|
||||
def cleanup
|
||||
return cleanup_nonces, cleanup_associations
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
84
vendor/gems/ruby-openid-2.1.2/lib/openid/store/memory.rb
vendored
Normal file
84
vendor/gems/ruby-openid-2.1.2/lib/openid/store/memory.rb
vendored
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
require 'openid/store/interface'
|
||||
module OpenID
|
||||
module Store
|
||||
# An in-memory implementation of Store. This class is mainly used
|
||||
# for testing, though it may be useful for long-running single
|
||||
# process apps. Note that this store is NOT thread-safe.
|
||||
#
|
||||
# You should probably be looking at OpenID::Store::Filesystem
|
||||
class Memory < Interface
|
||||
|
||||
def initialize
|
||||
@associations = {}
|
||||
@associations.default = {}
|
||||
@nonces = {}
|
||||
end
|
||||
|
||||
def store_association(server_url, assoc)
|
||||
assocs = @associations[server_url]
|
||||
@associations[server_url] = assocs.merge({assoc.handle => deepcopy(assoc)})
|
||||
end
|
||||
|
||||
def get_association(server_url, handle=nil)
|
||||
assocs = @associations[server_url]
|
||||
assoc = nil
|
||||
if handle
|
||||
assoc = assocs[handle]
|
||||
else
|
||||
assoc = assocs.values.sort{|a,b| a.issued <=> b.issued}[-1]
|
||||
end
|
||||
|
||||
return assoc
|
||||
end
|
||||
|
||||
def remove_association(server_url, handle)
|
||||
assocs = @associations[server_url]
|
||||
if assocs.delete(handle)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def use_nonce(server_url, timestamp, salt)
|
||||
return false if (timestamp - Time.now.to_i).abs > Nonce.skew
|
||||
nonce = [server_url, timestamp, salt].join('')
|
||||
return false if @nonces[nonce]
|
||||
@nonces[nonce] = timestamp
|
||||
return true
|
||||
end
|
||||
|
||||
def cleanup_associations
|
||||
count = 0
|
||||
@associations.each{|server_url, assocs|
|
||||
assocs.each{|handle, assoc|
|
||||
if assoc.expires_in == 0
|
||||
assocs.delete(handle)
|
||||
count += 1
|
||||
end
|
||||
}
|
||||
}
|
||||
return count
|
||||
end
|
||||
|
||||
def cleanup_nonces
|
||||
count = 0
|
||||
now = Time.now.to_i
|
||||
@nonces.each{|nonce, timestamp|
|
||||
if (timestamp - now).abs > Nonce.skew
|
||||
@nonces.delete(nonce)
|
||||
count += 1
|
||||
end
|
||||
}
|
||||
return count
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def deepcopy(o)
|
||||
Marshal.load(Marshal.dump(o))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
68
vendor/gems/ruby-openid-2.1.2/lib/openid/store/nonce.rb
vendored
Normal file
68
vendor/gems/ruby-openid-2.1.2/lib/openid/store/nonce.rb
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
require 'openid/cryptutil'
|
||||
require 'date'
|
||||
require 'time'
|
||||
|
||||
module OpenID
|
||||
module Nonce
|
||||
DEFAULT_SKEW = 60*60*5
|
||||
TIME_FMT = '%Y-%m-%dT%H:%M:%SZ'
|
||||
TIME_STR_LEN = '0000-00-00T00:00:00Z'.size
|
||||
@@NONCE_CHRS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
TIME_VALIDATOR = /\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ/
|
||||
|
||||
@skew = DEFAULT_SKEW
|
||||
|
||||
# The allowed nonce time skew in seconds. Defaults to 5 hours.
|
||||
# Used for checking nonce validity, and by stores' cleanup methods.
|
||||
def Nonce.skew
|
||||
@skew
|
||||
end
|
||||
|
||||
def Nonce.skew=(new_skew)
|
||||
@skew = new_skew
|
||||
end
|
||||
|
||||
# Extract timestamp from a nonce string
|
||||
def Nonce.split_nonce(nonce_str)
|
||||
timestamp_str = nonce_str[0...TIME_STR_LEN]
|
||||
raise ArgumentError if timestamp_str.size < TIME_STR_LEN
|
||||
raise ArgumentError unless timestamp_str.match(TIME_VALIDATOR)
|
||||
ts = Time.parse(timestamp_str).to_i
|
||||
raise ArgumentError if ts < 0
|
||||
return ts, nonce_str[TIME_STR_LEN..-1]
|
||||
end
|
||||
|
||||
# Is the timestamp that is part of the specified nonce string
|
||||
# within the allowed clock-skew of the current time?
|
||||
def Nonce.check_timestamp(nonce_str, allowed_skew=nil, now=nil)
|
||||
allowed_skew = skew if allowed_skew.nil?
|
||||
begin
|
||||
stamp, foo = split_nonce(nonce_str)
|
||||
rescue ArgumentError # bad timestamp
|
||||
return false
|
||||
end
|
||||
now = Time.now.to_i unless now
|
||||
|
||||
# times before this are too old
|
||||
past = now - allowed_skew
|
||||
|
||||
# times newer than this are too far in the future
|
||||
future = now + allowed_skew
|
||||
|
||||
return (past <= stamp and stamp <= future)
|
||||
end
|
||||
|
||||
# generate a nonce with the specified timestamp (defaults to now)
|
||||
def Nonce.mk_nonce(time = nil)
|
||||
salt = CryptUtil::random_string(6, @@NONCE_CHRS)
|
||||
if time.nil?
|
||||
t = Time.now.getutc
|
||||
else
|
||||
t = Time.at(time).getutc
|
||||
end
|
||||
time_str = t.strftime(TIME_FMT)
|
||||
return time_str + salt
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue