apache-authtkt 1.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_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: []