Set Ruckus Unleashed 200.7 / ZoneDirector DPSK passwords / DVLANs
This sample code allows you to extract the DPSK configuration from a ZoneDirector or Unleashed backup, then create a new backup containing your edited configuration.
Newer versions of Unleashed let you directly upload user-defined passwords, so this code isn't useful for modern APs.
DANGER
This code is super-hacky, and is totally unsupported.
But if everything goes wrong, then a factory reset then a restore of the original backup should get you back up and running.
Bash Function (using Python)
sh
rks_dpsk() {
RKS_DPSK_ACTION="$1" RKS_INPUT_PATH="$2" RKS_DPSK_PATH="$3" RKS_OUTPUT_PATH="$4" python3 - <<END
import gzip
import io
import os
import struct
import tarfile
import xml.etree.ElementTree as ET
rks_dpsk_action = os.environ['RKS_DPSK_ACTION']
rks_input_path = os.environ['RKS_INPUT_PATH']
rks_dpsk_path = os.environ['RKS_DPSK_PATH']
rks_output_path = os.environ['RKS_OUTPUT_PATH']
def __tac_decrypt(path: str) -> io.BytesIO:
(xor_int, xor_flip) = struct.unpack('QQ', b')\x1aB\x05\xbd,\xd6\xf25\xad\xb8\xe0?T\xc58')
struct_int8 = struct.Struct('Q')
output_file = io.BytesIO()
previous_input_int = 0
with open(path, "rb") as input_file:
input_data = input_file.read()
for input_int in struct.unpack_from(str(len(input_data) // 8) + 'Q', input_data):
output_bytes = struct_int8.pack(previous_input_int ^ xor_int ^ input_int)
xor_int ^= xor_flip
previous_input_int = input_int
output_file.write(output_bytes)
output_padding = int.from_bytes(output_bytes[-1:], 'big') & 0xf
output_file.seek(-output_padding, os.SEEK_END)
output_file.truncate()
output_file.seek(0)
return output_file
def __tac_encrypt(input_data: bytes, output_path: str):
(xor_int, xor_flip) = struct.unpack('QQ', b')\x1aB\x05\xbd,\xd6\xf25\xad\xb8\xe0?T\xc58')
struct_int8 = struct.Struct('Q')
with open(output_path, "wb") as output_file:
input_blocks = len(input_data) // 8
output_int = 0
for input_int in struct.unpack_from(str(input_blocks) + "Q", input_data):
output_int ^= xor_int ^ input_int
xor_int ^= xor_flip
output_file.write(struct_int8.pack(output_int))
input_block = input_data[input_blocks * 8:]
input_padding = 8 - len(input_block)
input_int = struct_int8.unpack(input_block.ljust(8, bytes([input_padding | input_padding << 4])))[0]
output_int ^= xor_int ^ input_int
output_file.write(struct_int8.pack(output_int))
def __encode_attributes(xml_bytes: bytes, offset: int) -> bytes:
xml_str = xml_bytes.decode("utf-8")
root = ET.fromstring(xml_str)
for element in root.iter():
for attr in list(element.attrib):
if attr.startswith('x-'):
element.attrib[attr] = ''.join(chr(ord(letter) + offset) for letter in element.attrib[attr])
return ET.tostring(root, encoding="utf-8")
def extract_dpsk(backup_path: str, dpsk_path: str):
"""Extract decrypted DPSK config from backup"""
with open(dpsk_path, 'wb') as dpsk_file, __tac_decrypt(backup_path) as backup_file:
with tarfile.open(fileobj = backup_file) as tar:
extracted = tar.extractfile('etc/airespider/dpsk-list.xml').read()
decoded = __encode_attributes(extracted, -1)
dpsk_file.write(decoded)
def replace_dpsk(backup_path: str, dpsk_path: str, output_path: str):
"""Create new backup with encrypted DPSK config"""
with open(dpsk_path, 'rb') as dpsk_file:
encoded = __encode_attributes(dpsk_file.read(), 1)
with __tac_decrypt(backup_path) as input_backup, gzip.open(input_backup, 'rb') as input_tarfile:
tar_buffer = io.BytesIO(input_tarfile.read())
tar_buffer.seek(0)
with tarfile.open(fileobj = tar_buffer, mode='a') as output_tar:
tar_info = tarfile.TarInfo('etc/airespider/dpsk-list.xml')
tar_info.size = len(encoded)
output_tar.addfile(tar_info, io.BytesIO(encoded))
tar_buffer.seek(0)
output_tgz = io.BytesIO()
with gzip.open(output_tgz, 'wb') as output_gzip:
output_gzip.write(tar_buffer.read())
output_tgz.seek(0)
__tac_encrypt(output_tgz.read(), output_path)
def rks_dpsk(action: str,backup_path: str, dpsk_path: str, output_path: str | None = None):
"""Extract or replace backup DPSK config"""
if action == 'extract':
extract_dpsk(backup_path, dpsk_path)
elif action == 'replace':
replace_dpsk(backup_path, dpsk_path, output_path)
rks_dpsk(rks_dpsk_action, rks_input_path, rks_dpsk_path, rks_output_path)
END
}
Usage
Backup your ZoneDirector or Unleashed AP
Extract the DPSK config
shell
$ rks_dpsk 'extract' 'test_ul.bak' 'test_dpsk.xml'
Edit the extracted DPSK config
Create a new backup containing your modifed DPSK config
shell
$ rks_dpsk 'replace' 'test_ul.bak' 'test_dpsk.xml' 'test_ul_modded.bak'
- Restore the new backup to your ZoneDirector or Unleashed AP