Initial push 0.2.0
This commit is contained in:
BIN
code/node_modules/radius/test/captures/aruba_mac_auth.packet
generated
vendored
Normal file
BIN
code/node_modules/radius/test/captures/aruba_mac_auth.packet
generated
vendored
Normal file
Binary file not shown.
BIN
code/node_modules/radius/test/captures/cisco_accounting.packet
generated
vendored
Normal file
BIN
code/node_modules/radius/test/captures/cisco_accounting.packet
generated
vendored
Normal file
Binary file not shown.
BIN
code/node_modules/radius/test/captures/cisco_accounting_response.packet
generated
vendored
Normal file
BIN
code/node_modules/radius/test/captures/cisco_accounting_response.packet
generated
vendored
Normal file
Binary file not shown.
BIN
code/node_modules/radius/test/captures/cisco_mac_auth.packet
generated
vendored
Normal file
BIN
code/node_modules/radius/test/captures/cisco_mac_auth.packet
generated
vendored
Normal file
Binary file not shown.
BIN
code/node_modules/radius/test/captures/cisco_mac_auth_reject.packet
generated
vendored
Normal file
BIN
code/node_modules/radius/test/captures/cisco_mac_auth_reject.packet
generated
vendored
Normal file
Binary file not shown.
BIN
code/node_modules/radius/test/captures/eap_request.packet
generated
vendored
Normal file
BIN
code/node_modules/radius/test/captures/eap_request.packet
generated
vendored
Normal file
Binary file not shown.
BIN
code/node_modules/radius/test/captures/invalid_register.packet
generated
vendored
Normal file
BIN
code/node_modules/radius/test/captures/invalid_register.packet
generated
vendored
Normal file
Binary file not shown.
BIN
code/node_modules/radius/test/captures/motorola_accounting.packet
generated
vendored
Normal file
BIN
code/node_modules/radius/test/captures/motorola_accounting.packet
generated
vendored
Normal file
Binary file not shown.
16
code/node_modules/radius/test/dictionaries/dictionary.airespace
generated
vendored
Normal file
16
code/node_modules/radius/test/dictionaries/dictionary.airespace
generated
vendored
Normal 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
|
||||
11
code/node_modules/radius/test/dictionaries/dictionary.aruba
generated
vendored
Normal file
11
code/node_modules/radius/test/dictionaries/dictionary.aruba
generated
vendored
Normal 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
|
||||
8
code/node_modules/radius/test/dictionaries/dictionary.number_vendor_name
generated
vendored
Normal file
8
code/node_modules/radius/test/dictionaries/dictionary.number_vendor_name
generated
vendored
Normal 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
|
||||
3
code/node_modules/radius/test/dictionaries/dictionary.test1
generated
vendored
Normal file
3
code/node_modules/radius/test/dictionaries/dictionary.test1
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
ATTRIBUTE Attribute-Test1 244 string
|
||||
|
||||
$INCLUDE dictionary.test2
|
||||
4
code/node_modules/radius/test/dictionaries/dictionary.test2
generated
vendored
Normal file
4
code/node_modules/radius/test/dictionaries/dictionary.test2
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
ATTRIBUTE Attribute-Test2 245 string
|
||||
|
||||
# don't do anything crazy like loop forever
|
||||
$INCLUDE dictionary.test1
|
||||
3
code/node_modules/radius/test/dictionaries/dictionary.test_tunnel_type
generated
vendored
Normal file
3
code/node_modules/radius/test/dictionaries/dictionary.test_tunnel_type
generated
vendored
Normal 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
970
code/node_modules/radius/test/radius.test.js
generated
vendored
Executable 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();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user