1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
# encoding: UTF-8
require 'sha1'
require 'xmlrpc/client'
require 'timeout'
module Mauve
class Authentication
ORDER = []
def authenticate(login, password)
raise ArgumentError.new("Login must be a string, not a #{login.class}") if String != login.class
raise ArgumentError.new("Password must be a string, not a #{password.class}") if String != password.class
raise ArgumentError.new("Login or/and password is/are empty.") if login.empty? || password.empty?
return false unless Mauve::Configuration.current.people.has_key?(login)
false
end
def logger
self.class.logger
end
def self.logger
@logger ||= Log4r::Logger.new(self.to_s)
end
def self.authenticate(login, password)
result = false
ORDER.each do |klass|
auth = klass.new
result = begin
auth.authenticate(login, password)
rescue StandardError => ex
logger.error "#{ex.class}: #{ex.to_s} during #{auth.class} for #{login}"
logger.debug ex.backtrace.join("\n")
false
end
if true == result
logger.info "Authenticated #{login} using #{auth.class.to_s}"
break
end
end
unless true == result
logger.info "Authentication for #{login} failed"
# Rate limit
sleep 5
end
result
end
end
class AuthBytemark < Authentication
Mauve::Authentication::ORDER << self
#
# TODO: allow configuration of where the server is.
#
def initialize (srv='auth.bytemark.co.uk', port=443)
raise ArgumentError.new("Server must be a String, not a #{srv.class}") if String != srv.class
raise ArgumentError.new("Port must be a Fixnum, not a #{port.class}") if Fixnum != port.class
@srv = srv
@port = port
@timeout = 7
end
## Not really needed.
def ping ()
begin
Timeout.timeout(@timeout) do
s = TCPSocket.open(@srv, @port)
s.close()
return true
end
rescue Timeout::Error => ex
return false
rescue => ex
return false
end
return false
end
def authenticate(login, password)
super
client = XMLRPC::Client.new(@srv,"/",@port,nil,nil,nil,nil,true,@timeout).proxy("bytemark.auth")
begin
challenge = client.getChallengeForUser(login)
response = Digest::SHA1.new.update(challenge).update(password).hexdigest
client.login(login, response)
return true
rescue XMLRPC::FaultException => fault
logger.warn "Authentication for #{login} failed: #{fault.faultCode}: #{fault.faultString}"
return false
rescue IOError => ex
logger.warn "#{ex.class} during auth for #{login} (#{ex.to_s})"
return false
end
end
end
class AuthLocal < Authentication
Mauve::Authentication::ORDER << self
def authenticate(login,password)
super
Digest::SHA1.hexdigest(password) == Mauve::Configuration.current.people[login].password
end
end
end
|