Initial push 0.2.0

This commit is contained in:
Alex Rennie-Lis
2024-04-05 22:57:26 +01:00
parent 93472ae250
commit 1d8bd0c989
55 changed files with 3515 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,16 @@
VENDOR Airespace 14179
BEGIN-VENDOR Airespace
ATTRIBUTE Airespace-Wlan-Id 1 integer
ATTRIBUTE Airespace-QOS-Level 2 integer
ATTRIBUTE Airespace-DSCP 3 integer
ATTRIBUTE Airespace-8021p-Tag 4 integer
ATTRIBUTE Airespace-Interface-Name 5 string
ATTRIBUTE Airespace-ACL-Name 6 string
VALUE Airespace-QOS-Level Bronze 3
VALUE Airespace-QOS-Level Silver 0
VALUE Airespace-QOS-Level Gold 1
VALUE Airespace-QOS-Level Platinum 2
END-VENDOR Airespace

View File

@@ -0,0 +1,11 @@
# Aruba attributes
VENDORATTR 14823 Aruba-User-Role 1 string
VENDORATTR 14823 Aruba-User-Vlan 2 integer
VENDORATTR 14823 Aruba-Priv-Admin-User 3 integer
VENDORATTR 14823 Aruba-Admin-Role 4 string
VENDORATTR 14823 Aruba-Essid-Name 5 String
VENDORATTR 14823 Aruba-Location-Id 6 string
VENDORATTR 14823 Aruba-Port-Id 7 string
VENDORATTR 14823 Aruba-Template-User 8 string
VENDORATTR 14823 Aruba-Named-User-Vlan 9 string
VENDORATTR 14823 Aruba-AP-Group 10 string

View File

@@ -0,0 +1,8 @@
VENDOR 123Foo 995486
BEGIN-VENDOR 123Foo
ATTRIBUTE 1Integer 1 integer
END-VENDOR 123Foo
VENDORATTR 995486 1String 2 string
VENDORATTR 995486 12345 3 string

View File

@@ -0,0 +1,3 @@
ATTRIBUTE Attribute-Test1 244 string
$INCLUDE dictionary.test2

View File

@@ -0,0 +1,4 @@
ATTRIBUTE Attribute-Test2 245 string
# don't do anything crazy like loop forever
$INCLUDE dictionary.test1

View File

@@ -0,0 +1,3 @@
# Fake tunnel type to be loaded before ATTRIBUTE Tunnel-Type is defined
VALUE Tunnel-Type TESTTUNNEL 31

970
code/node_modules/radius/test/radius.test.js generated vendored Executable file
View File

@@ -0,0 +1,970 @@
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();
}
});