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 +1 -1
- data/cul-handles.gemspec +79 -0
- data/lib/cul/handles/base_message.rb +121 -0
- data/lib/cul/handles/base_request.rb +153 -0
- data/lib/cul/handles/base_response.rb +191 -0
- data/lib/cul/handles/challenge_answer_request.rb +46 -0
- data/lib/cul/handles/challenge_response.rb +23 -0
- data/lib/cul/handles/client.rb +113 -0
- data/lib/cul/handles/create_handle_request.rb +22 -0
- data/lib/cul/handles/delete_handle_request.rb +22 -0
- data/lib/cul/handles/delete_value_request.rb +14 -0
- data/lib/cul/handles/handle_value_request.rb +90 -0
- data/lib/cul/handles/hdl.rb +244 -0
- data/lib/cul/handles/modify_value_request.rb +10 -0
- data/lib/cul/handles/resolution_request.rb +31 -0
- data/lib/cul/handles/resolution_response.rb +168 -0
- data/lib/cul/handles/session_request.rb +126 -0
- data/lib/cul/handles/session_setup_response.rb +25 -0
- data/lib/cul/handles/set_value_request.rb +6 -0
- metadata +24 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/cul-handles.gemspec
ADDED
@@ -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
|