ga_verify 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/ga-verify +33 -0
- data/bin/ga-verifyd +24 -0
- data/gen-rb/ga-verify_constants.rb +10 -0
- data/gen-rb/ga-verify_types.rb +18 -0
- data/gen-rb/verifier.rb +85 -0
- data/if/ga-verify.thrift +11 -0
- data/lib/ga_verify.rb +1 -0
- data/lib/ga_verify/client.rb +21 -0
- data/lib/ga_verify/handler.rb +48 -0
- data/lib/ga_verify/paths.rb +11 -0
- data/lib/ga_verify/server.rb +19 -0
- data/lib/ga_verify/thrift.rb +9 -0
- metadata +88 -0
data/bin/ga-verify
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
_SELF=File.readlink(__FILE__) rescue __FILE__
|
3
|
+
_ROOT=File.expand_path(File.dirname(_SELF) + '/../lib')
|
4
|
+
$LOAD_PATH.push _ROOT
|
5
|
+
|
6
|
+
require 'ga_verify/paths'
|
7
|
+
options = {
|
8
|
+
:socket => GAVerify::Paths.default_socket,
|
9
|
+
}
|
10
|
+
|
11
|
+
require 'optparse'
|
12
|
+
|
13
|
+
optparse = OptionParser.new do |opts|
|
14
|
+
opts.banner += " USER TOKEN"
|
15
|
+
opts.on(
|
16
|
+
'-s', '--socket PATH',
|
17
|
+
"Default: #{options[:socket]}"
|
18
|
+
) do |path|
|
19
|
+
options[:socket] = path
|
20
|
+
end
|
21
|
+
end
|
22
|
+
optparse.parse!
|
23
|
+
|
24
|
+
if ARGV.size != 2
|
25
|
+
STDERR.write optparse.help
|
26
|
+
exit 1
|
27
|
+
end
|
28
|
+
user, token = ARGV[0], ARGV[1].to_i
|
29
|
+
|
30
|
+
require 'ga_verify/client'
|
31
|
+
result = GAVerify::Client.new(options).check_user(user, token)
|
32
|
+
puts GAVerify::Result::VALUE_MAP[result]
|
33
|
+
exit result
|
data/bin/ga-verifyd
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
_SELF=File.readlink(__FILE__) rescue __FILE__
|
3
|
+
_ROOT=File.expand_path(File.dirname(_SELF) + '/../lib')
|
4
|
+
$LOAD_PATH.push _ROOT
|
5
|
+
|
6
|
+
require 'ga_verify/paths'
|
7
|
+
options = {
|
8
|
+
:socket => GAVerify::Paths.default_socket,
|
9
|
+
}
|
10
|
+
|
11
|
+
require 'optparse'
|
12
|
+
|
13
|
+
optparse = OptionParser.new do |opts|
|
14
|
+
opts.on(
|
15
|
+
'-s', '--socket PATH',
|
16
|
+
"Default: #{options[:socket]}"
|
17
|
+
) do |path|
|
18
|
+
options[:socket] = path
|
19
|
+
end
|
20
|
+
end
|
21
|
+
optparse.parse!
|
22
|
+
|
23
|
+
require 'ga_verify/server'
|
24
|
+
GAVerify::Server.new(options[:socket]).serve!
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#
|
2
|
+
# Autogenerated by Thrift
|
3
|
+
#
|
4
|
+
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
5
|
+
#
|
6
|
+
|
7
|
+
|
8
|
+
module GAVerify
|
9
|
+
module Result
|
10
|
+
SUCCESS = 0
|
11
|
+
BAD_TOKEN = 1
|
12
|
+
BAD_USER = 2
|
13
|
+
NO_GOOGLE_AUTH = 3
|
14
|
+
VALUE_MAP = {0 => "SUCCESS", 1 => "BAD_TOKEN", 2 => "BAD_USER", 3 => "NO_GOOGLE_AUTH"}
|
15
|
+
VALID_VALUES = Set.new([SUCCESS, BAD_TOKEN, BAD_USER, NO_GOOGLE_AUTH]).freeze
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/gen-rb/verifier.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
#
|
2
|
+
# Autogenerated by Thrift
|
3
|
+
#
|
4
|
+
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'thrift'
|
8
|
+
require 'ga-verify_types'
|
9
|
+
|
10
|
+
module GAVerify
|
11
|
+
module Verifier
|
12
|
+
class Client
|
13
|
+
include ::Thrift::Client
|
14
|
+
|
15
|
+
def check_user(name, token)
|
16
|
+
send_check_user(name, token)
|
17
|
+
return recv_check_user()
|
18
|
+
end
|
19
|
+
|
20
|
+
def send_check_user(name, token)
|
21
|
+
send_message('check_user', Check_user_args, :name => name, :token => token)
|
22
|
+
end
|
23
|
+
|
24
|
+
def recv_check_user()
|
25
|
+
result = receive_message(Check_user_result)
|
26
|
+
return result.success unless result.success.nil?
|
27
|
+
raise ::Thrift::ApplicationException.new(::Thrift::ApplicationException::MISSING_RESULT, 'check_user failed: unknown result')
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
class Processor
|
33
|
+
include ::Thrift::Processor
|
34
|
+
|
35
|
+
def process_check_user(seqid, iprot, oprot)
|
36
|
+
args = read_args(iprot, Check_user_args)
|
37
|
+
result = Check_user_result.new()
|
38
|
+
result.success = @handler.check_user(args.name, args.token)
|
39
|
+
write_result(result, oprot, 'check_user', seqid)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
# HELPER FUNCTIONS AND STRUCTURES
|
45
|
+
|
46
|
+
class Check_user_args
|
47
|
+
include ::Thrift::Struct, ::Thrift::Struct_Union
|
48
|
+
NAME = 1
|
49
|
+
TOKEN = 2
|
50
|
+
|
51
|
+
FIELDS = {
|
52
|
+
NAME => {:type => ::Thrift::Types::STRING, :name => 'name'},
|
53
|
+
TOKEN => {:type => ::Thrift::Types::I32, :name => 'token'}
|
54
|
+
}
|
55
|
+
|
56
|
+
def struct_fields; FIELDS; end
|
57
|
+
|
58
|
+
def validate
|
59
|
+
end
|
60
|
+
|
61
|
+
::Thrift::Struct.generate_accessors self
|
62
|
+
end
|
63
|
+
|
64
|
+
class Check_user_result
|
65
|
+
include ::Thrift::Struct, ::Thrift::Struct_Union
|
66
|
+
SUCCESS = 0
|
67
|
+
|
68
|
+
FIELDS = {
|
69
|
+
SUCCESS => {:type => ::Thrift::Types::I32, :name => 'success', :enum_class => GAVerify::Result}
|
70
|
+
}
|
71
|
+
|
72
|
+
def struct_fields; FIELDS; end
|
73
|
+
|
74
|
+
def validate
|
75
|
+
unless @success.nil? || GAVerify::Result::VALID_VALUES.include?(@success)
|
76
|
+
raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, 'Invalid value of field success!')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
::Thrift::Struct.generate_accessors self
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
data/if/ga-verify.thrift
ADDED
data/lib/ga_verify.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'ga_verify/client'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'ga_verify/thrift'
|
2
|
+
require 'ga_verify/paths'
|
3
|
+
|
4
|
+
require 'thrift'
|
5
|
+
|
6
|
+
module GAVerify
|
7
|
+
class Client
|
8
|
+
def initialize options={}
|
9
|
+
options[:socket] ||= GAVerify::Paths.default_socket
|
10
|
+
socket = Thrift::UNIXSocket.new(options[:socket])
|
11
|
+
transport = Thrift::FramedTransport.new(socket)
|
12
|
+
protocol = Thrift::BinaryProtocol.new(transport)
|
13
|
+
@client = GAVerify::Verifier::Client.new(protocol)
|
14
|
+
transport.open
|
15
|
+
end
|
16
|
+
|
17
|
+
def method_missing *args
|
18
|
+
@client.send *args
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'ga_verify/thrift'
|
2
|
+
require 'ga_verify/paths'
|
3
|
+
|
4
|
+
require 'rotp'
|
5
|
+
|
6
|
+
module GAVerify
|
7
|
+
class Handler
|
8
|
+
def initialize
|
9
|
+
@last_seen = Hash.new(0)
|
10
|
+
@used_tokens = Hash.new{Hash.new(0)}
|
11
|
+
end
|
12
|
+
|
13
|
+
def check_user user, token
|
14
|
+
unless user =~ /^[a-z]+$/
|
15
|
+
return GAVerify::Result::BAD_USER
|
16
|
+
end
|
17
|
+
unless File.exists? "/home/#{user}"
|
18
|
+
return GAVerify::Result::BAD_USER
|
19
|
+
end
|
20
|
+
path = GAVerify::Paths.config_path(user)
|
21
|
+
unless File.exists? path
|
22
|
+
return GAVerify::Result::NO_GOOGLE_AUTH
|
23
|
+
end
|
24
|
+
now = Time.now.to_i
|
25
|
+
# Max one login every 15s
|
26
|
+
if @last_seen[user] >= now - 15
|
27
|
+
return GAVerify::Result::BAD_TOKEN
|
28
|
+
end
|
29
|
+
@last_seen[user] = now
|
30
|
+
|
31
|
+
secret = File.open(path, 'r').first.strip
|
32
|
+
totp = ROTP::TOTP.new(secret)
|
33
|
+
|
34
|
+
# Allow +- 1 token
|
35
|
+
times = [now - 30, now, now + 30]
|
36
|
+
if times.any?{|time| totp.verify(token, time)}
|
37
|
+
# disallow token re-use within 10 minutes
|
38
|
+
if @used_tokens[user][token] < now - 600
|
39
|
+
@used_tokens[user][token] = now
|
40
|
+
# Cleanup
|
41
|
+
@used_tokens[user].reject!{|k,v| used_tokens[user][token] < now - 600}
|
42
|
+
return GAVerify::Result::SUCCESS
|
43
|
+
end
|
44
|
+
end
|
45
|
+
return GAVerify::Result::BAD_TOKEN
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'ga_verify/handler'
|
2
|
+
|
3
|
+
require 'thrift'
|
4
|
+
|
5
|
+
module GAVerify
|
6
|
+
class Server < GAVerify::Handler
|
7
|
+
def initialize socket_path
|
8
|
+
handler = GAVerify::Handler.new
|
9
|
+
processor = GAVerify::Verifier::Processor.new handler
|
10
|
+
transport = Thrift::FramedTransportFactory.new
|
11
|
+
socket = Thrift::UNIXServerSocket.new(socket_path)
|
12
|
+
@server = Thrift::NonblockingServer.new processor, socket, transport
|
13
|
+
end
|
14
|
+
|
15
|
+
def serve!
|
16
|
+
@server.serve
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ga_verify
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Fred Emmott
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-08-01 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rotp
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.3.0
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: thrift
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 0.6.0
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id002
|
37
|
+
description: Provides a unix socket for validating tokens
|
38
|
+
email:
|
39
|
+
- mail@fredemmott.co.uk
|
40
|
+
executables:
|
41
|
+
- ga-verify
|
42
|
+
- ga-verifyd
|
43
|
+
extensions: []
|
44
|
+
|
45
|
+
extra_rdoc_files: []
|
46
|
+
|
47
|
+
files:
|
48
|
+
- bin/ga-verifyd
|
49
|
+
- bin/ga-verify
|
50
|
+
- lib/ga_verify.rb
|
51
|
+
- lib/ga_verify/paths.rb
|
52
|
+
- lib/ga_verify/thrift.rb
|
53
|
+
- lib/ga_verify/client.rb
|
54
|
+
- lib/ga_verify/handler.rb
|
55
|
+
- lib/ga_verify/server.rb
|
56
|
+
- gen-rb/verifier.rb
|
57
|
+
- gen-rb/ga-verify_constants.rb
|
58
|
+
- gen-rb/ga-verify_types.rb
|
59
|
+
- if/ga-verify.thrift
|
60
|
+
homepage: https://github.com/fredemmott/ga-verify
|
61
|
+
licenses: []
|
62
|
+
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: "0"
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: "0"
|
80
|
+
requirements: []
|
81
|
+
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 1.7.2
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: Thrift client and server for validating google authenticator tokens
|
87
|
+
test_files: []
|
88
|
+
|