cul-handles 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|