UNPKG

radius

Version:
971 lines (809 loc) 28.2 kB
var testCase = require('nodeunit').testCase; var radius = require('../lib/radius'); var fs = require('fs'); var crypto = require('crypto'); var secret; var test_args = {}; module.exports = testCase({ setUp: function(callback) { secret = "nearbuy"; callback(); }, tearDown: function(callback) { radius.unload_dictionaries(); callback(); }, test_decode_mac_auth: function(test) { var raw_packet = fs.readFileSync(__dirname + '/captures/aruba_mac_auth.packet'); radius.load_dictionary(__dirname + '/dictionaries/dictionary.aruba'); var decoded = radius.decode({ packet: raw_packet, secret: secret }); test.equal( decoded.code, 'Access-Request' ); test.equal( decoded.identifier, 58 ); test.equal( decoded.length, 208 ); var expected_attrs = { 'NAS-IP-Address': '10.0.0.90', 'NAS-Port': 0, 'NAS-Port-Type': 'Wireless-802.11', 'User-Name': '7c:c5:37:ff:f8:af', 'User-Password': '7c:c5:37:ff:f8:af', 'Calling-Station-Id': '7CC537FFF8AF', 'Called-Station-Id': '000B86F02068', 'Service-Type': 'Login-User', 'Vendor-Specific': { 'Aruba-Essid-Name': 'muir-aruba-guest', 'Aruba-Location-Id': '00:1a:1e:c6:b0:ca', 'Aruba-AP-Group': 'cloud-cp' }, 'Message-Authenticator': new Buffer('f8a12329c7ed5a6e2568515243efb918', 'hex') }; test.deepEqual( decoded.attributes, expected_attrs ); test.done(); }, test_decode_mac_auth_without_secret: function(test) { var raw_packet = fs.readFileSync(__dirname + '/captures/aruba_mac_auth.packet'); radius.load_dictionary(__dirname + '/dictionaries/dictionary.aruba'); var decoded = radius.decode_without_secret({ packet: raw_packet }); test.equal( decoded.code, 'Access-Request' ); test.equal( decoded.identifier, 58 ); test.equal( decoded.length, 208 ); var expected_attrs = { 'NAS-IP-Address': '10.0.0.90', 'NAS-Port': 0, 'NAS-Port-Type': 'Wireless-802.11', 'User-Name': '7c:c5:37:ff:f8:af', 'User-Password': null, // this is an encrypted field, and so cannot be read without the password 'Calling-Station-Id': '7CC537FFF8AF', 'Called-Station-Id': '000B86F02068', 'Service-Type': 'Login-User', 'Vendor-Specific': { 'Aruba-Essid-Name': 'muir-aruba-guest', 'Aruba-Location-Id': '00:1a:1e:c6:b0:ca', 'Aruba-AP-Group': 'cloud-cp' }, 'Message-Authenticator': new Buffer('f8a12329c7ed5a6e2568515243efb918', 'hex') }; test.deepEqual( decoded.attributes, expected_attrs ); decoded = radius.decode({ secret: secret, packet: radius.encode({ secret: secret, code: "Access-Request", attributes: { 'User-Name': 'Caenogaean-asphyxia', 'User-Password': 'barratry-Wertherism' } }) }); test.equal( decoded.attributes['User-Password'], 'barratry-Wertherism' ); test.done(); }, // make sure everthing is fine with no dictionaries test_decode_no_dicts: function(test) { var raw_packet = fs.readFileSync(__dirname + '/captures/aruba_mac_auth.packet'); radius.unload_dictionaries(); var orig_load = radius.load_dictionary; radius.load_dictionary = function() { }; var decoded = radius.decode({ packet: raw_packet, secret: secret }); test.equal( decoded.code, 'Access-Request' ); test.equal( decoded.identifier, 58 ); test.equal( decoded.length, 208 ); // no pretty attributes test.deepEqual( decoded.attributes, {} ); var expected_raw_attrs = [ [4, new Buffer([10, 0, 0, 90])], [5, new Buffer([0, 0, 0, 0])], [61, new Buffer([0, 0, 0, 19])], [1, new Buffer('7c:c5:37:ff:f8:af')], [2, new Buffer('eb2ef7e83ec1a05e04fb5c6d91e088569a990fa2b1b2dc6a0f048596081164cd', 'hex')], [31, new Buffer('7CC537FFF8AF')], [30, new Buffer('000B86F02068')], [6, new Buffer([0, 0, 0, 1])], [26, new Buffer('000039e705126d7569722d61727562612d6775657374', 'hex')], [26, new Buffer('000039e7061330303a31613a31653a63363a62303a6361', 'hex')], [26, new Buffer('000039e70a0a636c6f75642d6370', 'hex')], [80, new Buffer('f8a12329c7ed5a6e2568515243efb918', 'hex')] ]; test.deepEqual( decoded.raw_attributes, expected_raw_attrs ); radius.load_dictionary = orig_load; test.done(); }, // can make a "naked" packet test_encode_access_request: function(test) { radius.load_dictionary(__dirname + '/dictionaries/dictionary.aruba'); var attributes = [ ['User-Name', 'ornithopter-aliptic'], ['User-Password', 'nucleohistone-overwilily'], ['Service-Type', 'Login-User'], ['NAS-IP-Address', '169.134.68.136'], ['Vendor-Specific', 14823, [ ['Aruba-User-Role', 'cracked-tylote'], [2, 825] ]], ['Vendor-Specific', 14823, [['Aruba-Essid-Name', 'phene-dentinalgia']]] ]; var packet = radius.encode({ code: 'Access-Request', identifier: 123, attributes: attributes, secret: secret }); var decoded = radius.decode({ packet: packet, secret: secret }); test.equal( decoded.code, 'Access-Request' ); test.equal( decoded.identifier, 123 ); var expected_attrs = { 'User-Name': 'ornithopter-aliptic', 'User-Password': 'nucleohistone-overwilily', 'Service-Type': 'Login-User', 'NAS-IP-Address': '169.134.68.136', 'Vendor-Specific': { 'Aruba-User-Role': 'cracked-tylote', 'Aruba-User-Vlan': 825, 'Aruba-Essid-Name': 'phene-dentinalgia' } }; test.deepEqual( decoded.attributes, expected_attrs ); test.done(); }, test_decode_hash_attributes: function(test) { var attrs = { 'User-Name': 'ornithopter-aliptic', 'User-Password': 'nucleohistone-overwilily', 'Service-Type': 'Login-User', 'NAS-IP-Address': '169.134.68.136' }; var packet = radius.encode({ code: 'Access-Request', identifier: 123, attributes: attrs, secret: secret }); var decoded = radius.decode({ packet: packet, secret: secret }); test.equal( decoded.code, 'Access-Request' ); test.equal( decoded.identifier, 123 ); test.deepEqual( decoded.attributes, attrs ); test.done(); }, test_throws_on_nested_hash_attributes: function(test) { var attrs = { 'User-Name': 'ornithopter-aliptic', 'User-Password': 'nucleohistone-overwilily', 'Service-Type': 'Login-User', 'NAS-IP-Address': '169.134.68.136', 'Vendor-Specific': { 'Aruba-User-Role': 'cracked-tylote', 'Aruba-User-Vlan': 825, 'Aruba-Essid-Name': 'phene-dentinalgia' } }; test.throws(function() { var packet = radius.encode({ code: 'Access-Request', identifier: 123, attributes: attrs, secret: secret }); }); test.done(); }, // test that our encoded packet matches bit-for-bit with a "real" // RADIUS packet test_encode_bit_for_bit: function(test) { var raw_packet = fs.readFileSync(__dirname + '/captures/aruba_mac_auth.packet'); radius.load_dictionary(__dirname + '/dictionaries/dictionary.aruba'); var encoded = radius.encode({ code: 'Access-Request', identifier: 58, authenticator: new Buffer('4a45fae086d9e114286b37b5f371ec6c', 'hex'), attributes: [ ['NAS-IP-Address', '10.0.0.90'], ['NAS-Port', 0], ['NAS-Port-Type', 'Wireless-802.11'], ['User-Name', '7c:c5:37:ff:f8:af'], ['User-Password', '7c:c5:37:ff:f8:af'], ['Calling-Station-Id', '7CC537FFF8AF'], ['Called-Station-Id', '000B86F02068'], ['Service-Type', 'Login-User'], ['Vendor-Specific', 14823, [['Aruba-Essid-Name', 'muir-aruba-guest']]], ['Vendor-Specific', 14823, [['Aruba-Location-Id', '00:1a:1e:c6:b0:ca']]], ['Vendor-Specific', 14823, [['Aruba-AP-Group', 'cloud-cp']]] ], secret: secret, add_message_authenticator: true }); test.equal( encoded.toString('hex'), raw_packet.toString('hex') ); test.done(); }, // encode will choose a random identifier for you if you don't provide one test_encode_random_identifer: function(test) { var decoded = radius.decode({ packet: radius.encode({ code: 'Access-Request', secret: secret }), secret: secret }); test.ok( decoded.identifier >= 0 && decoded.identifier < 256 ); var starting_id = decoded.identifier; // if you are unlucky this is an infinite loop while (true) { decoded = radius.decode({ packet: radius.encode({ code: 'Access-Request', secret: secret }), secret: secret }); if (decoded.identifier != starting_id) break; } test.ok( true ); test.done(); }, // given a previously decoded packet, prepare a response packet test_packet_response: function(test) { var raw_packet = fs.readFileSync(__dirname + '/captures/cisco_mac_auth.packet'); var decoded = radius.decode({ packet: raw_packet, secret: secret }); var response = radius.encode_response({ packet: decoded, code: 'Access-Reject', secret: secret }); var raw_response = fs.readFileSync(__dirname + '/captures/cisco_mac_auth_reject.packet'); test.equal( response.toString('hex'), raw_response.toString('hex') ); test.done(); }, // response needs to include proxy state test_response_include_proxy_state: function(test) { var request_with_proxy = radius.decode({ packet: radius.encode({ code: 'Access-Request', secret: secret, attributes: [ ['User-Name', 'ascribe-despairer'], ['Proxy-State', new Buffer('womanhouse-Pseudotsuga')], ['User-Password', 'ridiculous'], ['Proxy-State', new Buffer('regretfully-unstability')] ] }), secret: secret }); var decoded_response = radius.decode({ packet: radius.encode_response({ packet: request_with_proxy, code: 'Access-Reject', secret: secret }), secret: secret }); var expected_raw_attributes = [ [radius.attr_name_to_id('Proxy-State'), new Buffer('womanhouse-Pseudotsuga')], [radius.attr_name_to_id('Proxy-State'), new Buffer('regretfully-unstability')] ]; test.deepEqual( decoded_response.raw_attributes, expected_raw_attributes ); test.done(); }, // dont accidentally strip null bytes when encoding test_password_encode: function(test) { var decoded = radius.decode({ packet: radius.encode({ code: 'Access-Request', authenticator: new Buffer('426edca213c1bf6e005e90a64105ca3a', 'hex'), attributes: [['User-Password', 'ridiculous']], secret: secret }), secret: secret }); test.equal( decoded.attributes['User-Password'], 'ridiculous' ); test.done(); }, accounting_group: { setUp: function(cb) { radius.load_dictionary(__dirname + '/dictionaries/dictionary.airespace'); test_args = {}; test_args.raw_acct_request = fs.readFileSync(__dirname + '/captures/cisco_accounting.packet'); test_args.expected_acct_attrs = { 'User-Name': 'user_7C:C5:37:FF:F8:AF_134', 'NAS-Port': 1, 'NAS-IP-Address': '10.0.3.4', 'Framed-IP-Address': '10.2.0.252', 'NAS-Identifier': 'Cisco 4400 (Anchor)', 'Vendor-Specific': { 'Airespace-Wlan-Id': 2 }, 'Acct-Session-Id': '4fecc41e/7c:c5:37:ff:f8:af/9', 'Acct-Authentic': 'RADIUS', 'Tunnel-Type': [0x00, 'VLAN'], 'Tunnel-Medium-Type': [0x00, 'IEEE-802'], 'Tunnel-Private-Group-Id': 5, 'Acct-Status-Type': 'Start', 'Calling-Station-Id': '7c:c5:37:ff:f8:af', 'Called-Station-Id': '00:22:55:90:39:60' }; cb(); }, test_accounting: function(test) { var raw_acct_request = test_args.raw_acct_request; var decoded = radius.decode({ packet: raw_acct_request, secret: secret }); var expected_attrs = test_args.expected_acct_attrs; test.deepEqual( decoded.attributes, expected_attrs ); // test we can encode the same packet var encoded = radius.encode({ code: 'Accounting-Request', identifier: decoded.identifier, secret: secret, attributes: [ ['User-Name', 'user_7C:C5:37:FF:F8:AF_134'], ['NAS-Port', 1], ['NAS-IP-Address', '10.0.3.4'], ['Framed-IP-Address', '10.2.0.252'], ['NAS-Identifier', 'Cisco 4400 (Anchor)'], ['Vendor-Specific', 'Airespace', [['Airespace-Wlan-Id', 2]]], ['Acct-Session-Id', '4fecc41e/7c:c5:37:ff:f8:af/9'], ['Acct-Authentic', 'RADIUS'], ['Tunnel-Type', 0x00, 'VLAN'], ['Tunnel-Medium-Type', 0x00, 'IEEE-802'], ['Tunnel-Private-Group-Id', '5'], ['Acct-Status-Type', 'Start'], ['Calling-Station-Id', '7c:c5:37:ff:f8:af'], ['Called-Station-Id', '00:22:55:90:39:60'] ] }); test.equal( encoded.toString('hex'), raw_acct_request.toString('hex') ); var raw_acct_response = fs.readFileSync(__dirname + '/captures/cisco_accounting_response.packet'); encoded = radius.encode_response({ packet: decoded, secret: secret, code: 'Accounting-Response' }); test.equal( encoded.toString('hex'), raw_acct_response.toString('hex') ); test.done(); }, test_invalid_accounting_packet_authenticator: function(test) { var raw_acct_request = test_args.raw_acct_request; var expected_attrs = test_args.expected_acct_attrs; // detect invalid accounting packets test.throws( function() { radius.decode({ packet: raw_acct_request, secret: 'not-secret' }); } ); try { radius.decode({ packet: raw_acct_request, secret: 'not-secret' }); } catch (err) { test.deepEqual( err.decoded.attributes, expected_attrs ); } test.done(); } }, test_no_empty_strings: function(test) { var decoded = radius.decode({ secret: secret, packet: radius.encode({ code: 'Access-Request', attributes: [['User-Name', '']], secret: secret }) }); // don't send empty strings (see RFC2865) test.deepEqual( decoded.attributes, {} ); test.done(); }, test_repeated_attribute: function(test) { var decoded = radius.decode({ secret: secret, packet: radius.encode({ secret: secret, code: 'Access-Reject', attributes: [ ['Reply-Message', 'message one'], ['Reply-Message', 'message two'] ] }) }); var expected_attrs = { 'Reply-Message': ['message one', 'message two'] }; test.deepEqual( decoded.attributes, expected_attrs ); test.done(); }, test_dictionary_include: function(test) { radius.unload_dictionaries(); radius.add_dictionary(__dirname + '/dictionaries/dictionary.test1'); var decoded = radius.decode({ secret: secret, packet: radius.encode({ secret: secret, code: 'Access-Request', attributes: [['Attribute-Test1', 'foo'], ['Attribute-Test2', 'bar']] }) }); var expected_attrs = { 'Attribute-Test1': 'foo', 'Attribute-Test2': 'bar' }; test.deepEqual( decoded.attributes, expected_attrs ); test.done(); }, // make sure we can load the dicts in any order test_dictionary_out_of_order: function(test) { var dicts = fs.readdirSync(__dirname + '/../dictionaries'); // make sure we can load any dictionary first for (var i = 0; i < dicts.length; i++) { radius.unload_dictionaries(); radius.load_dictionary(__dirname + '/../dictionaries/' + dicts[i]); } // and spot check things actually work loaded out of order radius.unload_dictionaries(); radius.load_dictionary(__dirname + '/../dictionaries/dictionary.rfc2867'); radius.load_dictionary(__dirname + '/../dictionaries/dictionary.rfc2866'); var decoded = radius.decode({ secret: secret, packet: radius.encode({ code: 'Accounting-Request', secret: secret, attributes: [ ['Acct-Status-Type', 'Tunnel-Reject'] ] }) }); test.equal( decoded.attributes['Acct-Status-Type'], 'Tunnel-Reject' ); radius.unload_dictionaries(); radius.load_dictionary(__dirname + '/dictionaries/dictionary.test_tunnel_type'); radius.load_dictionaries(); decoded = radius.decode({ secret: secret, packet: radius.encode({ code: 'Accounting-Request', secret: secret, attributes: [ ['Tunnel-Type', 0x00, 'TESTTUNNEL'] ] }) }); var expected_attrs = {'Tunnel-Type': [0x00, 'TESTTUNNEL']}; test.deepEqual( decoded.attributes, expected_attrs ); test.done(); }, test_zero_identifer: function(test) { var decoded = radius.decode({ packet: radius.encode({ secret: secret, code: 'Access-Request', identifier: 0 }), secret: secret }); test.equal( decoded.identifier, 0 ); test.done(); }, test_date_type: function(test) { var raw_packet = fs.readFileSync(__dirname + '/captures/motorola_accounting.packet'); var decoded = radius.decode({ packet: raw_packet, secret: secret }); var epoch = 1349879753; test.equal( decoded.attributes['Event-Timestamp'].getTime(), epoch * 1000 ); var encoded = radius.encode({ code: 'Accounting-Request', identifier: decoded.identifier, attributes: [ ['User-Name', '00-1F-3B-8C-3A-15'], ['Acct-Status-Type', 'Start'], ['Acct-Session-Id', '1970D5A4-001F3B8C3A15-0000000001'], ['Calling-Station-Id', '00-1F-3B-8C-3A-15'], ['Called-Station-Id', 'B4-C7-99-77-59-D0:muir-moto-guest-site1'], ['NAS-Port', 1], ['NAS-Port-Type', 'Wireless-802.11'], ['NAS-IP-Address', '10.2.0.3'], ['NAS-Identifier', 'ap6532-70D5A4'], ['NAS-Port-Id', 'radio2'], ['Event-Timestamp', new Date(epoch * 1000)], ['Tunnel-Type', 0x00, 'VLAN' ], ['Tunnel-Medium-Type', 0x00, 'IEEE-802'], ['Tunnel-Private-Group-Id', '30'], ['Acct-Authentic', 'RADIUS'] ], secret: secret }); test.equal( encoded.toString('hex'), raw_packet.toString('hex') ); test.done(); }, test_date_type_non_mult_1000_ms: function(test) { var encoded; test.doesNotThrow(function() { encoded = radius.encode({ code: 'Accounting-Request', identifier: 123, attributes: [ ['Event-Timestamp', new Date(1403025894009)] ], secret: secret }); }); // truncates ms var decoded = radius.decode({ packet: encoded, secret: secret }); test.equal( decoded.attributes['Event-Timestamp'].getTime(), 1403025894000 ); test.done(); }, test_disconnect_request: function(test) { var encoded = radius.encode({ code: 'Disconnect-Request', identifier: 54, secret: secret, attributes: [ ['User-Name', 'mariticide-inquietation'], ['NAS-Identifier', 'Aglauros-charioted'] ] }); // check we did the non-user-password authenticator var got_authenticator = new Buffer(16); encoded.copy(got_authenticator, 0, 4); encoded.fill(0, 4, 20); var expected_authenticator = new Buffer(16); var hasher = crypto.createHash("md5"); hasher.update(encoded); hasher.update(secret); expected_authenticator.write(hasher.digest("binary"), 0, 16, "binary"); test.equal( got_authenticator.toString('hex'), expected_authenticator.toString('hex') ); // and make sure we check the authenticator when decoding test.throws(function() { radius.decode({ packet: encoded, secret: secret }); }); expected_authenticator.copy(encoded, 4, 0); test.doesNotThrow(function() { radius.decode({ packet: encoded, secret: secret }); }); test.done(); }, test_verify_response: function(test) { var request = radius.encode({ secret: secret, code: 'Accounting-Request', attributes: { 'User-Name': '00-1F-3B-8C-3A-15', 'Acct-Status-Type': 'Start' } }); var response = radius.encode_response({ secret: secret, code: 'Accounting-Response', packet: radius.decode({ packet: request, secret: secret }) }); test.ok( radius.verify_response({ request: request, response: response, secret: secret }) ); test.ok( !radius.verify_response({ request: request, response: response, secret: "Calliopsis-misbeholden" }) ); // response encoded with wrong secret response = radius.encode_response({ secret: "moyenne-paraboliform", code: 'Accounting-Response', packet: radius.decode({ packet: request, secret: secret }) }); test.ok( !radius.verify_response({ request: request, response: response, secret: secret }) ); test.done(); }, test_server_request: function(test) { var encoded1 = radius.encode({ code: 'Status-Server', identifier: 54, secret: secret, attributes: [ ['NAS-Identifier', 'symphilism-dicentrine'] ] }); var encoded2 = radius.encode({ code: 'Status-Server', identifier: 54, secret: secret, attributes: [ ['NAS-Identifier', 'symphilism-dicentrine'] ] }); // check we are doing a random authenticator var got_authenticator1 = new Buffer(16); encoded1.copy(got_authenticator1, 0, 4); var got_authenticator2 = new Buffer(16); encoded2.copy(got_authenticator2, 0, 4); test.notEqual( got_authenticator1.toString(), got_authenticator2.toString() ); var response = radius.encode_response({ code: 'Access-Accept', secret: secret, packet: radius.decode({packet: encoded1, secret: secret}) }); test.ok( radius.verify_response({ request: encoded1, response: response, secret: secret }) ); test.done(); }, test_vendor_names_with_numbers: function(test) { radius.load_dictionary(__dirname + '/dictionaries/dictionary.number_vendor_name'); var encoded = radius.encode({ code: "Access-Request", secret: secret, attributes: [ ['Vendor-Specific', '123Foo', [ ['1Integer', 478], ['1String', 'Zollernia-fibrovasal'], ['12345', 'myrmecophagoid-harn'] ]] ] }); var decoded = radius.decode({ packet: encoded, secret: secret }); test.equal( radius.vendor_name_to_id('123Foo'), 995486 ); test.deepEqual( decoded.attributes, { 'Vendor-Specific': { '1Integer': 478, '1String': 'Zollernia-fibrovasal', '12345': 'myrmecophagoid-harn' } } ); test.done(); }, message_authenticator_group: { setUp: function(cb) { secret = "testing123"; test_args = { raw_request: fs.readFileSync(__dirname + '/captures/eap_request.packet') }; test_args.parsed_request = radius.decode({ packet: test_args.raw_request, secret: secret }); cb(); }, // make sure we calculate the same Message-Authenticator test_calculate: function(test) { var attrs_without_ma = test_args.parsed_request.raw_attributes.filter(function(a) { return a[0] != radius.attr_name_to_id('Message-Authenticator'); }); var encoded = radius.encode({ code: test_args.parsed_request.code, identifier: test_args.parsed_request.identifier, authenticator: test_args.parsed_request.authenticator, attributes: attrs_without_ma, secret: secret }); test.equal( encoded.toString('hex'), test_args.raw_request.toString('hex') ); test.done(); }, // encode_response should calculate the appropriate Message-Authenticator test_encode_response: function(test) { var response = radius.encode_response({ code: "Access-Accept", secret: secret, packet: test_args.parsed_request }); var parsed_response = radius.decode({ packet: response, secret: secret }); // calculate expected Message-Authenticator var empty = new Buffer(16); empty.fill(0); var expected_response = radius.encode({ code: "Access-Accept", identifier: test_args.parsed_request.identifier, authenticator: test_args.parsed_request.authenticator, attributes: [["Message-Authenticator", empty]], secret: secret }); // expected_response's authenticator is correct, but Message-Authenticator is wrong // (it's all 0s). make sure verify_response checks both test.ok( !radius.verify_response({ request: test_args.raw_request, response: expected_response, secret: secret }) ); // put back the request's authenticator test_args.parsed_request.authenticator.copy(expected_response, 4); var expected_ma = radius.calculate_message_authenticator(expected_response, secret); test.equal( parsed_response.attributes["Message-Authenticator"].toString("hex"), expected_ma.toString("hex") ); test.ok( radius.verify_response({ request: test_args.raw_request, response: response, secret: secret }) ); test.done(); }, // response is missing Message-Authenticator, not okay test_response_missing_ma: function(test) { var bad_response = radius.encode({ code: "Access-Accept", identifier: test_args.parsed_request.identifier, authenticator: test_args.parsed_request.authenticator, attributes: [], secret: secret }); test.ok( !radius.verify_response({ request: test_args.raw_request, response: bad_response, secret: secret }) ); test.done(); }, // make sure we verify Message-Authenticator when decoding requests test_decode_verify: function(test) { test.throws(function() { radius.decode({ packet: test_args.raw_request, secret: 'wrong secret' }); }); test.done(); } }, test_utf8_strings: function(test) { var encoded = radius.encode({ secret: "密码", code: "Access-Request", attributes: { "User-Name": "金庸先生", "User-Password": "降龙十八掌" } }); var decoded = radius.decode({ packet: encoded, secret: "密码" }); test.deepEqual( { "User-Name": "金庸先生", "User-Password": "降龙十八掌" }, decoded.attributes ); test.done(); }, test_invalid_packet_attribute_length: function(test) { var invalid_packet = fs.readFileSync(__dirname + '/captures/invalid_register.packet'); var raw_packet = fs.readFileSync(__dirname + '/captures/aruba_mac_auth.packet'); // should fail decode packet attributes test.throws(function() { radius.decode_without_secret({ packet: invalid_packet }); } ); // should decode packet attributes test.doesNotThrow(function() { radius.decode_without_secret({ packet: raw_packet }); }); test.done(); }, test_tag_fields: function(test) { var decoded = radius.decode({ secret: secret, packet: radius.encode({ code: 'Accounting-Request', secret: secret, attributes: [ ['Tunnel-Type', 0x01, 'VLAN'], ['User-Name', 'honeymooner-hitched'], ] }) }); test.deepEqual( { 'Tunnel-Type': [ 1, 'VLAN'], 'User-Name': 'honeymooner-hitched' }, decoded.attributes ); test.done(); } });