cul-handles 0.1.0 → 0.2.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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
@@ -0,0 +1,79 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{cul-handles}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["James Stuart"]
12
+ s.date = %q{2009-11-11}
13
+ s.description = %q{Columbia client to deal with handle server}
14
+ s.email = %q{tastyhat@jamesstuart.org}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "cul-handles.gemspec",
27
+ "lib/cul-handles.rb",
28
+ "lib/cul/handles/base_message.rb",
29
+ "lib/cul/handles/base_request.rb",
30
+ "lib/cul/handles/base_response.rb",
31
+ "lib/cul/handles/challenge_answer_request.rb",
32
+ "lib/cul/handles/challenge_response.rb",
33
+ "lib/cul/handles/client.rb",
34
+ "lib/cul/handles/create_handle_request.rb",
35
+ "lib/cul/handles/delete_handle_request.rb",
36
+ "lib/cul/handles/delete_value_request.rb",
37
+ "lib/cul/handles/handle_value_request.rb",
38
+ "lib/cul/handles/hdl.rb",
39
+ "lib/cul/handles/modify_value_request.rb",
40
+ "lib/cul/handles/resolution_request.rb",
41
+ "lib/cul/handles/resolution_response.rb",
42
+ "lib/cul/handles/session_request.rb",
43
+ "lib/cul/handles/session_setup_response.rb",
44
+ "lib/cul/handles/set_value_request.rb",
45
+ "test/authn_test.rb",
46
+ "test/cul-handles_test.rb",
47
+ "test/dh_test.rb",
48
+ "test/resolution_test.rb",
49
+ "test/test_helper.rb",
50
+ "test/unsigned_integer_test.rb"
51
+ ]
52
+ s.homepage = %q{http://github.com/tastyhat/cul-handles}
53
+ s.rdoc_options = ["--charset=UTF-8"]
54
+ s.require_paths = ["lib"]
55
+ s.rubygems_version = %q{1.3.5}
56
+ s.summary = %q{CUL Handle Client}
57
+ s.test_files = [
58
+ "test/authn_test.rb",
59
+ "test/cul-handles_test.rb",
60
+ "test/dh_test.rb",
61
+ "test/resolution_test.rb",
62
+ "test/test_helper.rb",
63
+ "test/unsigned_integer_test.rb"
64
+ ]
65
+
66
+ if s.respond_to? :specification_version then
67
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
68
+ s.specification_version = 3
69
+
70
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
71
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
72
+ else
73
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
74
+ end
75
+ else
76
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
77
+ end
78
+ end
79
+
@@ -0,0 +1,121 @@
1
+ module Cul
2
+ module Handles
3
+ class BaseMessage
4
+ include Hdl
5
+ def initialize
6
+ @SHA1 = Digest::SHA1.new()
7
+ @MD5 = Digest::MD5.new()
8
+ @digest = [nil,@MD5,@SHA1]
9
+ @majorVersion = 2 # default
10
+ @minorVersion = 1 # default
11
+ @digestAlg = 2 # SHA1 = 2, MD5 = 1
12
+ @digestLength = 20 # SHA1 = 20 octets, MD5 = 16
13
+ @sequenceNumber = [0,0,0,0]
14
+
15
+ end
16
+
17
+ def authoritative=(val)
18
+ if(val)
19
+ @opFlag[MSG_FLAG_AUTH_INDEX] |= MSG_FLAG_AUTH
20
+ else
21
+ @opFlag[MSG_FLAG_AUTH_INDEX] &= ~MSG_FLAG_AUTH
22
+ end
23
+ end
24
+ def authoritative()
25
+ return @opFlag[MSG_FLAG_AUTH_INDEX] & MSG_FLAG_AUTH > 0
26
+ end
27
+ def certify=(val)
28
+ if(val)
29
+ @opFlag[MSG_FLAG_CERT_INDEX] |= MSG_FLAG_CERT
30
+ else
31
+ @opFlag[MSG_FLAG_CERT_INDEX] &= ~MSG_FLAG_CERT
32
+ end
33
+ end
34
+ def certify()
35
+ return @opFlag[MSG_FLAG_CERT_INDEX] & MSG_FLAG_CERT > 0
36
+ end
37
+ def encrypt=(val)
38
+ if(val)
39
+ @opFlag[MSG_FLAG_ENCR_INDEX] |= MSG_FLAG_ENCR
40
+ else
41
+ @opFlag[MSG_FLAG_ENCR_INDEX] &= ~MSG_FLAG_ENCR
42
+ end
43
+ end
44
+ def encrypt()
45
+ return @opFlag[MSG_FLAG_ENCR_INDEX] & MSG_FLAG_ENCR > 0
46
+ end
47
+ def recursive=(val)
48
+ if(val)
49
+ @opFlag[MSG_FLAG_RECU_INDEX] |= MSG_FLAG_RECU
50
+ else
51
+ @opFlag[MSG_FLAG_RECU_INDEX] &= ~MSG_FLAG_RECU
52
+ end
53
+ end
54
+ def recursive()
55
+ return @opFlag[MSG_FLAG_RECU_INDEX] & MSG_FLAG_RECU > 0
56
+ end
57
+ def cacheCertify=(val)
58
+ if(val)
59
+ @opFlag[MSG_FLAG_CACR_INDEX] |= MSG_FLAG_CACR
60
+ else
61
+ @opFlag[MSG_FLAG_CACR_INDEX] &= ~MSG_FLAG_CACR
62
+ end
63
+ end
64
+ def cacheCertify()
65
+ return @opFlag[MSG_FLAG_CACR_INDEX] & MSG_FLAG_CACR > 0
66
+ end
67
+ def continuous=(val)
68
+ if(val)
69
+ @opFlag[MSG_FLAG_CONT_INDEX] |= MSG_FLAG_CONT
70
+ else
71
+ @opFlag[MSG_FLAG_CONT_INDEX] &= ~MSG_FLAG_CONT
72
+ end
73
+ end
74
+ def continuous()
75
+ return @opFlag[MSG_FLAG_CONT_INDEX] & MSG_FLAG_CONT > 0
76
+ end
77
+ def keepAlive=(val)
78
+ if(val)
79
+ @opFlag[MSG_FLAG_KPAL_INDEX] |= MSG_FLAG_KPAL
80
+ else
81
+ @opFlag[MSG_FLAG_KPAL_INDEX] &= ~MSG_FLAG_KPAL
82
+ end
83
+ end
84
+ def keepAlive()
85
+ return @opFlag[MSG_FLAG_KPAL_INDEX] & MSG_FLAG_KPAL > 0
86
+ end
87
+ def publicOnly=(val)
88
+ if(val)
89
+ @opFlag[MSG_FLAG_PUBL_INDEX] |= MSG_FLAG_PUBL
90
+ else
91
+ @opFlag[MSG_FLAG_PUBL_INDEX] &= ~MSG_FLAG_PUBL
92
+ end
93
+ end
94
+ def publicOnly()
95
+ return @opFlag[MSG_FLAG_PUBL_INDEX] & MSG_FLAG_PUBL > 0
96
+ end
97
+ def returnRequestDigest=(val)
98
+ if(val)
99
+ @opFlag[MSG_FLAG_RRDG_INDEX] |= MSG_FLAG_RRDG
100
+ else
101
+ @opFlag[MSG_FLAG_RRDG_INDEX] &= ~MSG_FLAG_RRDG
102
+ end
103
+ end
104
+ def returnRequestDigest()
105
+ return @opFlag[MSG_FLAG_RRDG_INDEX] & MSG_FLAG_RRDG > 0
106
+ end
107
+ def digestAlg=(val)
108
+ if(val == 1)
109
+ @digest = @MD5
110
+ @digestLength = 16
111
+ elsif(val == 2)
112
+ @digest = @SHA1
113
+ @digestLength = 20
114
+ else
115
+ @digest = nil
116
+ @digestLength = 0
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,153 @@
1
+ module Cul
2
+ module Handles
3
+ class BaseRequest < BaseMessage
4
+ def initialize()
5
+ super()
6
+ @body = []
7
+ @opFlag = [0,0,0,0]
8
+ @recursionCount = [0]
9
+ @messageFlag = [0,0]
10
+ @messageLength = [0,0,0,0]
11
+ @siteInfoSerial = [0xff,0xff]
12
+ @sessionId = [0,0,0,0]
13
+ @credential = [0,0,0,0]
14
+ end
15
+ def valid?()
16
+ return true
17
+ end
18
+ def opCode=(val)
19
+ @opCode=asBytes(val)
20
+ end
21
+ def opCode()
22
+ @opCode
23
+ end
24
+ def opFlag=(val)
25
+ @opFlag=asBytes(val)
26
+ end
27
+ def opFlag()
28
+ fromBytes(@opFlag)
29
+ end
30
+ def requestId=(val)
31
+ @requestId=asBytes(val)
32
+ end
33
+ def requestId()
34
+ fromBytes(@requestId)
35
+ end
36
+ def sessionId=(val)
37
+ @sessionId=asBytes(val)
38
+ end
39
+ def sessionId()
40
+ @sessionId
41
+ end
42
+ def siteInfoSerial=(val)
43
+ if val < 0
44
+ @siteInfoSerial=asBytes(65536 + val)[-2..-1]
45
+ else
46
+ @siteInfoSerial = asBytes(val)[-2..-1]
47
+ end
48
+ end
49
+ def siteInfoSerial()
50
+ return fromBytes(@siteInfoSerial)
51
+ end
52
+ def sequenceNumber()
53
+ fromBytes(@sequenceNumber)
54
+ end
55
+ def sequenceNumber=(val)
56
+ @sequenceNumber=asBytes(val)
57
+ end
58
+ def recursionCount()
59
+ fromBytes(@recursionCount)
60
+ end
61
+ def recursionCount=(val)
62
+ @recursionCount=asBytes(val)
63
+ end
64
+ def expirationTime()
65
+ fromBytes(@expirationTime)
66
+ end
67
+ def expirationTime=(val)
68
+ @expirationTime=asBytes(val)
69
+ end
70
+ def responseCode=(val)
71
+ @responseCode=asBytes(val)
72
+ end
73
+ def responseCode
74
+ @responseCode
75
+ end
76
+ def credentialVersion()
77
+ return []
78
+ end
79
+ def credentialReserved()
80
+ return []
81
+ end
82
+ def credentialOptions()
83
+ return []
84
+ end
85
+ def credentialSigner()
86
+ return []
87
+ end
88
+ def credentialType()
89
+ return []
90
+ end
91
+ def credentialDigestAlg()
92
+ return []
93
+ end
94
+ def encodeCredential()
95
+ creds = [].concat(self.credentialVersion).concat(self.credentialReserved).concat(self.credentialOptions()).concat(self.credentialSigner).concat(self.credentialType)
96
+ creds = asBytes(creds.length).concat(creds)
97
+ @credential = creds
98
+ end
99
+ def credential()
100
+ @credential
101
+ end
102
+ def messageFlag=(val)
103
+ @messageFlag = val
104
+ end
105
+ def envelope
106
+ e = [@majorVersion, @minorVersion]
107
+ e.concat(@messageFlag)
108
+ e.concat(@sessionId)
109
+ e.concat(@requestId)
110
+ e.concat(@sequenceNumber)
111
+ e.concat(asBytes(@body.length + 24 + @credential.length))
112
+ e
113
+ end
114
+ def messageFlag
115
+ return @messageFlag
116
+ end
117
+ def messageLength
118
+ @body.length + 24 + @credential.length
119
+ end
120
+ def header
121
+ result = [].concat(self.opCode)
122
+ result.concat(@responseCode)
123
+ result.concat(@opFlag)
124
+ result.concat(@siteInfoSerial)
125
+ result.concat(@recursionCount)
126
+ result.concat([0])
127
+ result.concat(@expirationTime)
128
+ result.concat(asBytes(@body.length))
129
+ return result
130
+ end
131
+ def body
132
+ return @body
133
+ end
134
+ def encodeBody()
135
+ return
136
+ end
137
+ def bodyLength
138
+ return asBytes(@body.length)
139
+ end
140
+ def digest(data)
141
+ return @SHA1.digest(data.pack('U*')).unpack('c*')
142
+ end
143
+ def packet
144
+ encodeBody()
145
+ encodeCredential()
146
+ result = envelope().concat(header())
147
+ result.concat(body())
148
+ result.concat(credential())
149
+ return result
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,191 @@
1
+ module Cul
2
+ module Handles
3
+
4
+ class BaseResponse < BaseMessage
5
+ include Hdl
6
+ def initialize
7
+ super()
8
+ @packet = []
9
+ @siteInfoSerial = [0,0]
10
+ @requestId = [0,0,0,0]
11
+ @sessionId = [0,0,0,0]
12
+ @opCode = [0,0,0,0]
13
+ @responseCode = [0,0,0,0]
14
+ @opFlag = [0,0,0,0]
15
+ @recursionCount = 0
16
+ @expirationTime = [0,0,0,0]
17
+ @bodyLength = 0
18
+ @debug = false
19
+ end
20
+ def debug=(val)
21
+ if(val)
22
+ @debug = true
23
+ else
24
+ @debug = false
25
+ end
26
+ end
27
+ def send(req,sock)
28
+ if not req.valid?()
29
+ raise "Request invalid: " + req.to_s
30
+ end
31
+ initialize()
32
+ bytes = req.packet
33
+ bctr = 0
34
+ puts "sending \n" + bytes.collect{|byte|
35
+ bctr = bctr + 1
36
+ if byte.nil?
37
+ "nil byte at " + bctr.to_s
38
+ else
39
+ "%02x" % byte
40
+ end
41
+ }.join if @debug
42
+ sent = sock.write(bytes.pack('C*'))
43
+
44
+ if sent != bytes.length
45
+ puts "Warning: Attempted to send " + bytes.length.to_s + "; actually sent " + sent.to_s
46
+ end
47
+ parseEnvelope(sock.recv(20).unpack('C*'))
48
+ puts "parsed envelope" if @debug
49
+ parseHeader(sock.recv(24).unpack('C*'))
50
+ puts "parsed header" if @debug
51
+ parseBody(sock.recv(@bodyLength).unpack('C*'))
52
+ puts "parsed body" if @debug
53
+ parseCredential(Array.new())
54
+ end
55
+ def parseEnvelope(data)
56
+ "parseEnvelope"
57
+ if(data.length != 20)
58
+ puts("Unexpected envelope length: " + data.length.to_s)
59
+ return
60
+ end
61
+ @packet.concat(data)
62
+ # version info
63
+ @majorVersion = data[0]
64
+ @minorVersion = data[1]
65
+ # message flag
66
+ mflag = data[2] # actually 2 octets, but second octet is reserved
67
+ if ((mflag & Hdl::ENV_FLAG_COMPRESSED) == Hdl::ENV_FLAG_COMPRESSED)
68
+ @compressed = true
69
+ end
70
+ if ((mflag & Hdl::ENV_FLAG_ENCRYPTED) == Hdl::ENV_FLAG_ENCRYPTED)
71
+ @encrypted = true
72
+ end
73
+ if ((mflag & Hdl::ENV_FLAG_TRUNCATED) == Hdl::ENV_FLAG_TRUNCATED)
74
+ @truncated = true
75
+ end
76
+ # session id
77
+ @sessionId = data[4..7]
78
+ # request id
79
+ @requestId = data[8..11]
80
+ # sequence number
81
+ @sequenceNumber = data[12..15]
82
+ # message length
83
+ @messageLength = data[16..19]
84
+ end
85
+ def sessionId
86
+ return fromBytes(@sessionId)
87
+ end
88
+ def requestId
89
+ return fromBytes(@requestId)
90
+ end
91
+ def parseHeader(data)
92
+ @packet.concat(data)
93
+ if(data.length != 24)
94
+ puts("Unexpected header length: " + data.length.to_s)
95
+ return
96
+ end
97
+ @opCode = data[0..3]
98
+ @responseCode = data[4..7]
99
+ @opFlag = data[8..11]
100
+ @siteInfoSerial = data[12..13]
101
+ @recursionCount = data[14]
102
+ @expirationTime = data[16..19]
103
+ @bodyLength = fromBytes(data[20..23])
104
+ if(@bodyLength < 1)
105
+ puts "Unexpected @bodyLength: " + @bodyLength.to_s
106
+ end
107
+ end
108
+ def opCode
109
+ return fromBytes(@opCode)
110
+ end
111
+ def responseCode
112
+ return fromBytes(@responseCode)
113
+ end
114
+ def success?
115
+ return @responseCode.eql?([0,0,0,1])
116
+ end
117
+ def siteInfoSerial
118
+ return fromBytes(@siteInfoSerial)
119
+ end
120
+ def parseBody(data)
121
+ offset = 0
122
+ @packet.concat(data)
123
+ # parse return digest
124
+ if self.returnRequestDigest()
125
+ self.digestAlg = data[offset]
126
+ if (@digestLength)
127
+ @messageDigest = data[1..(@digestLength)]
128
+ offset = 1 + @digestLength
129
+ else
130
+ @messageDigest = []
131
+ end
132
+ end
133
+ @body = data[offset...@bodyLength]
134
+ end
135
+ def body
136
+ @body
137
+ end
138
+ def parseCredential(data)
139
+ offset = 0
140
+ @packet.concat(data)
141
+ # parse credential
142
+ if (data.length > 0)
143
+ @credentialVersion = data[offset]
144
+ offset = offset + 2
145
+ @credentialOptions = data[offset..offset+1]
146
+ offset = offset + 2
147
+ @credential = data[offset...(offset+credentialLength)]
148
+ offset = offset + credentialLength
149
+ pstringData = readProtocolString(data,offset)
150
+ offset = offset + pstringData[0]
151
+ type = pstringData[1]
152
+ signedInfoLength = fromBytes(data[offset...offset+4])
153
+ offset = offset + 4
154
+ signedInfoAlg = nil
155
+ signedInfoData = nil
156
+ if signedInfoLength > 0
157
+ signedInfoEnd = offset + signedInfoLength
158
+ pstringData = readProtocolString(data,offset)
159
+ offset = offset + pstringData[0]
160
+ self.signedInfoAlg = pstringData[1]
161
+ self.signedInfoData = data[offset..-1]
162
+ offset = signedInfoEnd
163
+ end
164
+
165
+ end
166
+ end
167
+ def credential
168
+ @credential
169
+ end
170
+ def credentialType=(val)
171
+ @credentialType = val
172
+ end
173
+ def signedInfoAlg=(val)
174
+ @signedInfoAlg = val
175
+ end
176
+ def signedInfo=(val)
177
+ @signedInfo=val
178
+ end
179
+ def packet
180
+ @packet
181
+ end
182
+ def to_s
183
+ result = "opCode: " + opCode.to_s + "; responseCode: " + responseCode().to_s + " sessionId: " + fromBytes(@sessionId).to_s + "; requestId: " + fromBytes(@requestId).to_s + "; bodyLength: " + @bodyLength.to_s
184
+ if @bodyLength > 0
185
+ result = result + "; body: " + @packet[44...(44+@bodyLength)].pack('c*')
186
+ end
187
+ result
188
+ end
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,46 @@
1
+ module Cul
2
+ module Handles
3
+ class ChallengeAnswerRequest < BaseRequest
4
+ include Hdl
5
+ def initialize(nonce,digest,keyHandle, keyIndex)
6
+ super()
7
+ @nonce = nonce
8
+ @digest =digest
9
+ @opCode = asBytes(OC_CHALLENGE_RESPONSE)
10
+ @authenticationType = toProtocolString("HS_SECKEY")
11
+ @keyHandle = toProtocolString(keyHandle)
12
+ @keyIndex = asBytes(keyIndex)
13
+ @challengeResponse = []
14
+ @secret = []
15
+ self.responseCode = 0
16
+ self.authoritative=false
17
+ self.returnRequestDigest=false
18
+ self.encrypt=false
19
+ self.publicOnly=false
20
+ self.certify=false
21
+ self.cacheCertify=true
22
+ self.recursive=true
23
+ self.continuous=false
24
+ self.keepAlive=false
25
+ self.expirationTime=0
26
+ end
27
+ def body()
28
+ @body
29
+ end
30
+ def secret=(val)
31
+ @secret = val.unpack('U*').pack('C*')
32
+ end
33
+ def encodeBody()
34
+ digest = Digest::SHA1.new()
35
+ digest.update(@secret)
36
+ digest.update(@nonce.pack('C*'))
37
+ digest.update(@digest.pack('C*'))
38
+ digest.update(@secret)
39
+ prehash = digest.digest()
40
+ @challengeResponse = [0x02].concat(prehash.unpack('C*'))
41
+ @challengeResponse = asBytes(@challengeResponse.length).concat(@challengeResponse)
42
+ @body = [].concat(@authenticationType).concat(@keyHandle).concat(@keyIndex).concat(@challengeResponse)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,23 @@
1
+ module Cul
2
+ module Handles
3
+ class ChallengeResponse < BaseResponse
4
+ attr_reader :nonce, :digest
5
+ def parseBody(data)
6
+ # read digest
7
+ digestAlg = data[0]
8
+ if (digestAlg == 1)
9
+ @digest = data[1..16]
10
+ offset = 17
11
+ else
12
+ @digest = data[1..20]
13
+ offset = 21
14
+ end
15
+ arrayInfo = readByteArray(data,offset)
16
+ @nonce = arrayInfo[1]
17
+ end
18
+ def nonce
19
+ @nonce
20
+ end
21
+ end
22
+ end
23
+ end