apache_authtkt 2.0.0

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.
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: