267 lines
9.1 KiB
Ruby
267 lines
9.1 KiB
Ruby
require "test/unit"
|
|
require "openid/association"
|
|
|
|
module OpenID
|
|
class AssociationTestCase < Test::Unit::TestCase
|
|
def setup
|
|
# Use this funny way of getting a time so that it does not have
|
|
# fractional seconds, and so can be serialized exactly using our
|
|
# standard code.
|
|
issued = Time.at(Time.now.to_i)
|
|
lifetime = 600
|
|
|
|
@assoc = Association.new('handle', 'secret', issued,
|
|
lifetime, 'HMAC-SHA1')
|
|
end
|
|
|
|
def test_round_trip
|
|
assoc2 = Association.deserialize(@assoc.serialize())
|
|
[:handle, :secret, :lifetime, :assoc_type].each do |attr|
|
|
assert_equal(@assoc.send(attr), assoc2.send(attr))
|
|
end
|
|
end
|
|
|
|
def test_deserialize_failure
|
|
field_list = Util.kv_to_seq(@assoc.serialize)
|
|
kv = Util.seq_to_kv(field_list + [['monkeys', 'funny']])
|
|
assert_raises(ProtocolError) {
|
|
Association.deserialize(kv)
|
|
}
|
|
|
|
bad_version_list = field_list.dup
|
|
bad_version_list[0] = ['version', 'moon']
|
|
bad_version_kv = Util.seq_to_kv(bad_version_list)
|
|
assert_raises(ProtocolError) {
|
|
Association.deserialize(bad_version_kv)
|
|
}
|
|
end
|
|
|
|
def test_serialization_identity
|
|
assoc2 = Association.deserialize(@assoc.serialize)
|
|
assert_equal(@assoc, assoc2)
|
|
end
|
|
|
|
def test_expires_in
|
|
# Allow one second of slop
|
|
assert(@assoc.expires_in.between?(599,600))
|
|
assert(@assoc.expires_in(Time.now.to_i).between?(599,600))
|
|
assert_equal(0,@assoc.expires_in(Time.now.to_i + 10000),"negative expires_in")
|
|
end
|
|
|
|
def test_from_expires_in
|
|
start_time = Time.now
|
|
expires_in = @assoc.expires_in
|
|
assoc = Association.from_expires_in(expires_in,
|
|
@assoc.handle,
|
|
@assoc.secret,
|
|
@assoc.assoc_type)
|
|
|
|
# Allow one second of slop here for code execution time
|
|
assert_in_delta(1, assoc.expires_in, @assoc.expires_in)
|
|
[:handle, :secret, :assoc_type].each do |attr|
|
|
assert_equal(@assoc.send(attr), assoc.send(attr))
|
|
end
|
|
|
|
# Make sure the issued time is near the start
|
|
assert(assoc.issued >= start_time)
|
|
assert_in_delta(1, assoc.issued.to_f, start_time.to_f)
|
|
end
|
|
|
|
def test_sign_sha1
|
|
pairs = [['key1', 'value1'],
|
|
['key2', 'value2']]
|
|
|
|
[['HMAC-SHA256', "\xfd\xaa\xfe;\xac\xfc*\x988\xad\x05d6-"\
|
|
"\xeaVy\xd5\xa5Z.<\xa9\xed\x18\x82\\$"\
|
|
"\x95x\x1c&"],
|
|
['HMAC-SHA1', "\xe0\x1bv\x04\xf1G\xc0\xbb\x7f\x9a\x8b"\
|
|
"\xe9\xbc\xee}\\\xe5\xbb7*"],
|
|
].each do |assoc_type, expected|
|
|
assoc = Association.from_expires_in(3600, "handle", 'very_secret',
|
|
assoc_type)
|
|
sig = assoc.sign(pairs)
|
|
assert_equal(sig, expected)
|
|
|
|
m = Message.new(OPENID2_NS)
|
|
pairs.each { |k, v|
|
|
m.set_arg(OPENID_NS, k, v)
|
|
}
|
|
m.set_arg(BARE_NS, "not_an_openid_arg", "bogus")
|
|
|
|
signed_m = assoc.sign_message(m)
|
|
assert(signed_m.has_key?(OPENID_NS, 'sig'))
|
|
assert_equal(signed_m.get_arg(OPENID_NS, 'signed'),
|
|
'assoc_handle,key1,key2,ns,signed')
|
|
end
|
|
end
|
|
|
|
def test_sign_message_with_sig
|
|
assoc = Association.from_expires_in(3600, "handle", "very_secret",
|
|
"HMAC-SHA1")
|
|
m = Message.new(OPENID2_NS)
|
|
m.set_arg(OPENID_NS, 'sig', 'noise')
|
|
assert_raises(ArgumentError) {
|
|
assoc.sign_message(m)
|
|
}
|
|
end
|
|
|
|
def test_sign_message_with_signed
|
|
assoc = Association.from_expires_in(3600, "handle", "very_secret",
|
|
"HMAC-SHA1")
|
|
m = Message.new(OPENID2_NS)
|
|
m.set_arg(OPENID_NS, 'signed', 'fields')
|
|
assert_raises(ArgumentError) {
|
|
assoc.sign_message(m)
|
|
}
|
|
end
|
|
|
|
def test_sign_different_assoc_handle
|
|
assoc = Association.from_expires_in(3600, "handle", "very_secret",
|
|
"HMAC-SHA1")
|
|
m = Message.new(OPENID2_NS)
|
|
m.set_arg(OPENID_NS, 'assoc_handle', 'different')
|
|
assert_raises(ArgumentError) {
|
|
assoc.sign_message(m)
|
|
}
|
|
end
|
|
|
|
def test_sign_bad_assoc_type
|
|
@assoc.instance_eval { @assoc_type = 'Cookies' }
|
|
assert_raises(ProtocolError) {
|
|
@assoc.sign([])
|
|
}
|
|
end
|
|
|
|
def test_make_pairs
|
|
msg = Message.new(OPENID2_NS)
|
|
msg.update_args(OPENID2_NS, {
|
|
'mode' => 'id_res',
|
|
'identifier' => '=example',
|
|
'signed' => 'identifier,mode',
|
|
'sig' => 'cephalopod',
|
|
})
|
|
msg.update_args(BARE_NS, {'xey' => 'value'})
|
|
assoc = Association.from_expires_in(3600, '{sha1}', 'very_secret',
|
|
"HMAC-SHA1")
|
|
pairs = assoc.make_pairs(msg)
|
|
assert_equal([['identifier', '=example'],
|
|
['mode', 'id_res']], pairs)
|
|
end
|
|
|
|
def test_check_message_signature_no_signed
|
|
m = Message.new(OPENID2_NS)
|
|
m.update_args(OPENID2_NS, {'mode' => 'id_res',
|
|
'identifier' => '=example',
|
|
'sig' => 'coyote',
|
|
})
|
|
assoc = Association.from_expires_in(3600, '{sha1}', 'very_secret',
|
|
"HMAC-SHA1")
|
|
assert_raises(ProtocolError) {
|
|
assoc.check_message_signature(m)
|
|
}
|
|
end
|
|
|
|
def test_check_message_signature_no_sig
|
|
m = Message.new(OPENID2_NS)
|
|
m.update_args(OPENID2_NS, {'mode' => 'id_res',
|
|
'identifier' => '=example',
|
|
'signed' => 'mode',
|
|
})
|
|
assoc = Association.from_expires_in(3600, '{sha1}', 'very_secret',
|
|
"HMAC-SHA1")
|
|
assert_raises(ProtocolError) {
|
|
assoc.check_message_signature(m)
|
|
}
|
|
end
|
|
|
|
def test_check_message_signature_bad_sig
|
|
m = Message.new(OPENID2_NS)
|
|
m.update_args(OPENID2_NS, {'mode' => 'id_res',
|
|
'identifier' => '=example',
|
|
'signed' => 'mode',
|
|
'sig' => Util.to_base64('coyote'),
|
|
})
|
|
assoc = Association.from_expires_in(3600, '{sha1}', 'very_secret',
|
|
"HMAC-SHA1")
|
|
assert(!assoc.check_message_signature(m))
|
|
end
|
|
|
|
def test_check_message_signature_good_sig
|
|
m = Message.new(OPENID2_NS)
|
|
m.update_args(OPENID2_NS, {'mode' => 'id_res',
|
|
'identifier' => '=example',
|
|
'signed' => 'mode',
|
|
'sig' => Util.to_base64('coyote'),
|
|
})
|
|
assoc = Association.from_expires_in(3600, '{sha1}', 'very_secret',
|
|
"HMAC-SHA1")
|
|
class << assoc
|
|
# Override sign, because it's already tested elsewhere
|
|
def sign(pairs)
|
|
"coyote"
|
|
end
|
|
end
|
|
|
|
assert(assoc.check_message_signature(m))
|
|
end
|
|
end
|
|
|
|
class AssociationNegotiatorTestCase < Test::Unit::TestCase
|
|
def assert_equal_under(item1, item2)
|
|
val1 = yield(item1)
|
|
val2 = yield(item2)
|
|
assert_equal(val1, val2)
|
|
end
|
|
|
|
def test_copy
|
|
neg = AssociationNegotiator.new([['HMAC-SHA1', 'DH-SHA1']])
|
|
neg2 = neg.copy
|
|
assert_equal_under(neg, neg2) {|n| n.instance_eval{@allowed_types} }
|
|
assert(neg.object_id != neg2.object_id)
|
|
end
|
|
|
|
def test_add_allowed
|
|
neg = AssociationNegotiator.new([])
|
|
assert(!neg.allowed?('HMAC-SHA1', 'DH-SHA1'))
|
|
assert(!neg.allowed?('HMAC-SHA1', 'no-encryption'))
|
|
assert(!neg.allowed?('HMAC-SHA256', 'DH-SHA256'))
|
|
assert(!neg.allowed?('HMAC-SHA256', 'no-encryption'))
|
|
neg.add_allowed_type('HMAC-SHA1')
|
|
assert(neg.allowed?('HMAC-SHA1', 'DH-SHA1'))
|
|
assert(neg.allowed?('HMAC-SHA1', 'no-encryption'))
|
|
assert(!neg.allowed?('HMAC-SHA256', 'DH-SHA256'))
|
|
assert(!neg.allowed?('HMAC-SHA256', 'no-encryption'))
|
|
neg.add_allowed_type('HMAC-SHA256', 'DH-SHA256')
|
|
assert(neg.allowed?('HMAC-SHA1', 'DH-SHA1'))
|
|
assert(neg.allowed?('HMAC-SHA1', 'no-encryption'))
|
|
assert(neg.allowed?('HMAC-SHA256', 'DH-SHA256'))
|
|
assert(!neg.allowed?('HMAC-SHA256', 'no-encryption'))
|
|
assert_equal(neg.get_allowed_type, ['HMAC-SHA1', 'DH-SHA1'])
|
|
end
|
|
|
|
def test_bad_assoc_type
|
|
assert_raises(ProtocolError) {
|
|
AssociationNegotiator.new([['OMG', 'Ponies']])
|
|
}
|
|
end
|
|
|
|
def test_bad_session_type
|
|
assert_raises(ProtocolError) {
|
|
AssociationNegotiator.new([['HMAC-SHA1', 'OMG-Ponies']])
|
|
}
|
|
end
|
|
|
|
def test_default_negotiator
|
|
assert_equal(DefaultNegotiator.get_allowed_type,
|
|
['HMAC-SHA1', 'DH-SHA1'])
|
|
assert(DefaultNegotiator.allowed?('HMAC-SHA256', 'no-encryption'))
|
|
end
|
|
|
|
def test_encrypted_negotiator
|
|
assert_equal(EncryptedNegotiator.get_allowed_type,
|
|
['HMAC-SHA1', 'DH-SHA1'])
|
|
assert(!EncryptedNegotiator.allowed?('HMAC-SHA256', 'no-encryption'))
|
|
end
|
|
end
|
|
end
|