apache-authtkt 1.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_auth_tkt.rb +188 -0
  3. metadata +72 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 79c0570d80ebd51b02fedbaccad5d6dd4878a855
4
+ data.tar.gz: ad6beba55080206d6e402e2f7bf419d399d4d5d4
5
+ SHA512:
6
+ metadata.gz: 59e4aadf2e1c0109cad3bf619943db49672ce70205f9889bd8a83641dcbf975a36a7826d0fc1a4b4ee663391d98f74c66da9eed7587764f91139befd8eaff354
7
+ data.tar.gz: c157e47579aa31c6ba95df06bc0993964c14e1b337dd0f6cdf49df58bfd551e3d63beee4b9c8576d182e4a6e0bb066f30bc9942cda8f778ec76bf7b0f895c71d
@@ -0,0 +1,188 @@
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
+
22
+ class ApacheAuthTkt
23
+
24
+ attr_accessor :secret
25
+ attr_accessor :ipaddr
26
+ attr_accessor :digest_type
27
+ attr_accessor :conf_file
28
+ attr_accessor :error
29
+ attr_accessor :base64encode
30
+
31
+ def initialize(args)
32
+
33
+ #puts args.inspect
34
+
35
+ # set defaults
36
+ if (args.has_key? :ipaddr)
37
+ @ipaddr = args[:ipaddr]
38
+ else
39
+ @ipaddr = '0.0.0.0'
40
+ end
41
+
42
+ if (args.has_key? :secret)
43
+ @secret = args[:secret]
44
+ elsif (args.has_key? :conf_file)
45
+ @secret = _get_secret(args[:conf_file])
46
+ if (!@secret.length)
47
+ raise "Can't parse secret from " + args[:conf_file]
48
+ end
49
+ else
50
+ raise "Must pass 'secret' or 'conf_file'"
51
+ end
52
+
53
+ if (args[:digest_type])
54
+ @digest_type = args[:digest_type]
55
+ else
56
+ @digest_type = 'md5'
57
+ end
58
+
59
+ if (args.has_key? :base64encode)
60
+ @base64encode = args[:base64encode]
61
+ else
62
+ @base64encode = true
63
+ end
64
+
65
+
66
+ end
67
+
68
+ def _get_secret(filename)
69
+ # based on http://meso.net/mod_auth_tkt
70
+ if (!File.file? filename)
71
+ raise "#{filename} is not a file"
72
+ end
73
+ secret_str = ''
74
+ open(filename) do |file|
75
+ file.each do |line|
76
+ if line.include? 'TKTAuthSecret'
77
+ secret_str = line.gsub('TKTAuthSecret', '').strip.gsub("\"", '').gsub("'",'')
78
+ break
79
+ end
80
+ end
81
+ end
82
+ return secret_str
83
+ end
84
+
85
+ # from http://meso.net/mod_auth_tkt
86
+ # function adapted according to php: generates an IPv4 Internet network address
87
+ # from its Internet standard format (dotted string) representation.
88
+ def ip2long(ip)
89
+ long = 0
90
+ ip.split( /\./ ).reverse.each_with_index do |x, i|
91
+ long += x.to_i << ( i * 8 )
92
+ end
93
+ long
94
+ end
95
+
96
+ # based on http://meso.net/mod_auth_tkt
97
+ def create_ticket(user_opts={})
98
+ options = {
99
+ :user => 'guest',
100
+ :tokens => '',
101
+ :user_data => '',
102
+ :ignore_ip => false,
103
+ :ts => Time.now.to_i
104
+ }.merge(user_opts)
105
+
106
+ timestamp = options[:ts]
107
+ ip_address = options[:ignore_ip] ? '0.0.0.0' : @ipaddr
108
+ digest = get_digest(timestamp, ip_address, options[:user], options[:tokens], options[:user_data])
109
+ tkt = sprintf("%s%08x%s!%s!%s", digest, timestamp, options[:user], options[:tokens], options[:user_data])
110
+
111
+ if (@base64encode)
112
+ tkt = Base64.encode64(tkt).gsub("\n", '').strip
113
+ end
114
+
115
+ return tkt
116
+
117
+ end
118
+
119
+ def get_digest(ts, ipaddr, user, tokens, data)
120
+ ipts = [ip2long(ipaddr), ts].pack("NN")
121
+ digest0 = nil
122
+ digest = nil
123
+ raw = ipts + @secret + user + "\0" + tokens + "\0" + data
124
+ if (@digest_type == 'md5')
125
+ digest0 = Digest::MD5.hexdigest(raw)
126
+ digest = Digest::MD5.hexdigest(digest0 + @secret)
127
+ elsif (@digest_type == 'sha256')
128
+ digest0 = Digest::SHA256.hexdigest(raw)
129
+ digest = Digest::SHA256.hexdigest(digest0 + @secret)
130
+ else
131
+ raise "unsupported digest type: " + @digest_type
132
+ end
133
+ return digest
134
+ end
135
+
136
+ def validate_ticket(tkt, ipaddr='0.0.0.0')
137
+ parsed = parse_ticket(tkt)
138
+ if (!parsed)
139
+ return false
140
+ end
141
+ expected_digest = get_digest(parsed[:ts], ipaddr, parsed[:user], parsed[:tokens], parsed[:data])
142
+ if (expected_digest == parsed[:digest])
143
+ return parsed
144
+ else
145
+ return false
146
+ end
147
+ end
148
+
149
+ def parse_ticket(tkt)
150
+ # strip possible lead/trail quotes
151
+ tkt = tkt.gsub(/^"|"$/,'')
152
+
153
+ # test if base64 encoded before decoding
154
+ if (@base64encode && tkt.length % 4 == 0 && tkt =~ /^[A-Za-z0-9+\/=]+\Z/)
155
+ tkt = Base64.decode64(tkt)
156
+ end
157
+
158
+ # sanity checks
159
+ if (tkt.length < 40)
160
+ @error = "ticket string too short"
161
+ return false
162
+ end
163
+ if (!tkt.index('!'))
164
+ @error = "ticket missing !"
165
+ return false
166
+ end
167
+
168
+ # parse it
169
+ parts = tkt.split(/\!/)
170
+ parsed = {:tokens => '', :data => ''}
171
+ if (packed = parts[0].match('^(.{32})(.{8})(.+)$'))
172
+ parsed[:digest] = packed[1]
173
+ parsed[:ts] = packed[2].hex
174
+ parsed[:user] = packed[3]
175
+ if (parts.length == 3)
176
+ parsed[:tokens] = parts[1]
177
+ parsed[:data] = parts[2]
178
+ elsif (parts.length == 2)
179
+ parsed[:tokens] = parts[1]
180
+ end
181
+ else
182
+ @error = "invalid ticket pattern"
183
+ return false
184
+ end
185
+ return parsed
186
+ end
187
+
188
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: apache-authtkt
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Peter Karman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Ruby client for mod_auth_tkt. See http://www.openfusion.com.au/labs/mod_auth_tkt/
42
+ email: pkarman@mpr.org
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - lib/apache_auth_tkt.rb
48
+ homepage: https://github.com/APMG/apache-authtkt-ruby
49
+ licenses:
50
+ - Apache v2
51
+ metadata: {}
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubyforge_project: nowarning
68
+ rubygems_version: 2.2.2
69
+ signing_key:
70
+ specification_version: 4
71
+ summary: Ruby client for mod_auth_tkt
72
+ test_files: []