apache_authtkt 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/apache_authtkt.rb +205 -0
  3. metadata +74 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 30514640ce14fbe685c0c66f4516d21f7e448e39
4
+ data.tar.gz: 943fbebbb53196bed4472d76c929d86ba3cd0619
5
+ SHA512:
6
+ metadata.gz: 4688616bc933b0732e9be7c0067994a85d0d855ad691641db49ffcefb19cb4bc8c7c3e367104af4c5a330b9217b1b0232755890c2df178a82879b1dfb2f8210d
7
+ data.tar.gz: 1858437c036dfbb33be18c09ac37f6b7c0876f3fdaaebc2dcdb08d4de270b2bcc0d44676c3a23e169531b3abdfb644a91477a603586c1aa7cbe0c8e066efa497
@@ -0,0 +1,205 @@
1
+ # ApacheAuthTkt is a Ruby client
2
+ # for mod_auth_tkt (http://www.openfusion.com.au/labs/mod_auth_tkt/)
3
+ #
4
+ # Copyright 2014 American Public Media Group
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ # dependencies
19
+ require 'rubygems'
20
+ require 'base64'
21
+ require 'digest'
22
+
23
+ class ApacheAuthTkt
24
+
25
+ attr_accessor :secret
26
+ attr_accessor :ipaddr
27
+ attr_accessor :digest_type
28
+ attr_accessor :conf_file
29
+ attr_accessor :error
30
+ attr_accessor :base64encode
31
+ attr_accessor :lifetime
32
+
33
+ def initialize(args)
34
+
35
+ #puts args.inspect
36
+
37
+ # set defaults
38
+ if (args.has_key? :ipaddr)
39
+ @ipaddr = args[:ipaddr]
40
+ else
41
+ @ipaddr = '0.0.0.0'
42
+ end
43
+
44
+ if (args.has_key? :secret)
45
+ @secret = args[:secret]
46
+ elsif (args.has_key? :conf_file)
47
+ @secret = _get_secret(args[:conf_file])
48
+ if (!@secret.length)
49
+ raise "Can't parse secret from " + args[:conf_file]
50
+ end
51
+ else
52
+ raise "Must pass 'secret' or 'conf_file'"
53
+ end
54
+
55
+ if (args[:digest_type])
56
+ @digest_type = args[:digest_type]
57
+ else
58
+ @digest_type = 'md5'
59
+ end
60
+
61
+ if (args.has_key? :base64encode)
62
+ @base64encode = args[:base64encode]
63
+ else
64
+ @base64encode = true
65
+ end
66
+
67
+ if (args.has_key? :lifetime)
68
+ @lifetime = args[:lifetime]
69
+ else
70
+ # 8 hours.
71
+ @lifetime = 28800
72
+ end
73
+
74
+ end
75
+
76
+ def _get_secret(filename)
77
+ # based on http://meso.net/mod_auth_tkt
78
+ if (!File.file? filename)
79
+ raise "#{filename} is not a file"
80
+ end
81
+ secret_str = ''
82
+ open(filename) do |file|
83
+ file.each do |line|
84
+ if line.include? 'TKTAuthSecret'
85
+ secret_str = line.gsub('TKTAuthSecret', '').strip.gsub("\"", '').gsub("'",'')
86
+ break
87
+ end
88
+ end
89
+ end
90
+ return secret_str
91
+ end
92
+
93
+ # from http://meso.net/mod_auth_tkt
94
+ # function adapted according to php: generates an IPv4 Internet network address
95
+ # from its Internet standard format (dotted string) representation.
96
+ def ip2long(ip)
97
+ long = 0
98
+ ip.split( /\./ ).reverse.each_with_index do |x, i|
99
+ long += x.to_i << ( i * 8 )
100
+ end
101
+ long
102
+ end
103
+
104
+ # based on http://meso.net/mod_auth_tkt
105
+ def create_ticket(user_opts={})
106
+ options = {
107
+ :user => 'guest',
108
+ :tokens => '',
109
+ :user_data => '',
110
+ :ignore_ip => false,
111
+ :ts => Time.now.to_i
112
+ }.merge(user_opts)
113
+
114
+ timestamp = options[:ts]
115
+ ip_address = options[:ignore_ip] ? '0.0.0.0' : @ipaddr
116
+ digest = get_digest(timestamp, ip_address, options[:user], options[:tokens], options[:user_data])
117
+ tkt = sprintf("%s%08x%s!%s!%s", digest, timestamp, options[:user], options[:tokens], options[:user_data])
118
+
119
+ if (@base64encode)
120
+ tkt = Base64.encode64(tkt).gsub("\n", '').strip
121
+ end
122
+
123
+ return tkt
124
+
125
+ end
126
+
127
+ def get_digest(ts, ipaddr, user, tokens, data)
128
+ ipts = [ip2long(ipaddr), ts].pack("NN")
129
+ digest0 = nil
130
+ digest = nil
131
+ raw = ipts + @secret + user + "\0" + tokens + "\0" + data
132
+ if (@digest_type == 'md5')
133
+ digest0 = Digest::MD5.hexdigest(raw)
134
+ digest = Digest::MD5.hexdigest(digest0 + @secret)
135
+ elsif (@digest_type == 'sha256')
136
+ digest0 = Digest::SHA256.hexdigest(raw)
137
+ digest = Digest::SHA256.hexdigest(digest0 + @secret)
138
+ else
139
+ raise "unsupported digest type: " + @digest_type
140
+ end
141
+ return digest
142
+ end
143
+
144
+ def validate_ticket(tkt, ipaddr='0.0.0.0')
145
+ parsed = parse_ticket(tkt)
146
+ if (!parsed)
147
+ return false
148
+ end
149
+ expected_digest = get_digest(parsed[:ts], ipaddr, parsed[:user], parsed[:tokens], parsed[:data])
150
+ if (expected_digest == parsed[:digest])
151
+ return parsed
152
+ else
153
+ return false
154
+ end
155
+ end
156
+
157
+ def parse_ticket(tkt)
158
+ # strip possible lead/trail quotes
159
+ tkt = tkt.gsub(/^"|"$/,'')
160
+
161
+ # test if base64 encoded before decoding
162
+ if (@base64encode && tkt.length % 4 == 0 && tkt =~ /^[A-Za-z0-9+\/=]+\Z/)
163
+ tkt = Base64.decode64(tkt)
164
+ end
165
+
166
+ # sanity checks
167
+ if (tkt.length < 40)
168
+ @error = "ticket string too short"
169
+ return false
170
+ end
171
+ if (!tkt.index('!'))
172
+ @error = "ticket missing !"
173
+ return false
174
+ end
175
+
176
+ # parse it
177
+ parts = tkt.split(/\!/)
178
+ parsed = {:tokens => '', :data => ''}
179
+ if (packed = parts[0].match('^(.{32})(.{8})(.+)$'))
180
+ parsed[:digest] = packed[1]
181
+ parsed[:ts] = packed[2].hex
182
+ parsed[:user] = packed[3]
183
+ if (parts.length == 3)
184
+ parsed[:tokens] = parts[1]
185
+ parsed[:data] = parts[2]
186
+ elsif (parts.length == 2)
187
+ parsed[:tokens] = parts[1]
188
+ end
189
+ else
190
+ @error = "invalid ticket pattern"
191
+ return false
192
+ end
193
+ return parsed
194
+ end
195
+
196
+ def expired?(tkt)
197
+ return false if @lifetime.nil?
198
+ parsed = self.parse_ticket(tkt)
199
+ if (!parsed)
200
+ return false
201
+ end
202
+ !(parsed[:ts] + @lifetime >= Time.now.to_i)
203
+ end
204
+
205
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: apache_authtkt
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - William Johnston
8
+ - Peter Karman
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-07-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rspec
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ description: Ruby client for mod_auth_tkt. See http://www.openfusion.com.au/labs/mod_auth_tkt/
43
+ email: wjohnston@mpr.org
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - lib/apache_authtkt.rb
49
+ homepage: https://github.com/APMG/apache-authtkt-ruby
50
+ licenses:
51
+ - Apache v2
52
+ metadata: {}
53
+ post_install_message:
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ requirements: []
68
+ rubyforge_project: nowarning
69
+ rubygems_version: 2.4.8
70
+ signing_key:
71
+ specification_version: 4
72
+ summary: Ruby client for mod_auth_tkt
73
+ test_files: []
74
+ has_rdoc: