示例#1
0
def test_set_password():
    '''Test the SETPASSWORD command'''
    dbconn = setup_test()
    dbdata = init_server(dbconn)

    conn = serverconn.ServerConnection()
    status = conn.connect('localhost', 2001)
    assert not status.error(
    ), f"test_set_password(): failed to connect to server: {status.info()}"

    # Moved all the test code to integration_setup.init_admin(), because that kind of setup is
    # needed for other tests.
    status = init_admin(conn, dbdata)
    assert not status.error(
    ), f"test_set_password(): init_admin failed: {status.info()}"

    badpassword = Password('MyS3cretPassw*rd')
    newpassword = Password('Renovate-Baggy-Grunt-Override')
    status = serverconn.setpassword(conn, badpassword.hashstring,
                                    newpassword.hashstring)
    assert status.error() and status['Code'] == 402, \
     "test_set_password: failed to catch bad password"

    status = serverconn.setpassword(conn, dbdata['admin_password'].hashstring,
                                    newpassword.hashstring)
    assert not status.error(), "test_set_password: failed to update password"

    conn.disconnect()
示例#2
0
def test_connect():
    '''Tests just the basic connection to the server and parsing the greeting'''
    conn = serverconn.ServerConnection()
    status = conn.connect('localhost', 2001)

    assert not status.error(
    ), f"test_connect(): failed to connect to server: {status.info()}"
    conn.disconnect()
示例#3
0
def test_reset_password():
    '''Tests password reset code'''
    dbconn = setup_test()
    dbdata = init_server(dbconn)

    conn = serverconn.ServerConnection()
    status = conn.connect('localhost', 2001)
    assert not status.error(
    ), f"test_login(): failed to connect to server: {status.info()}"

    password = Password('Linguini2Pegboard*Album')
    devid = '14142135-9c22-4d3e-84a3-2aa281f65714'
    keypair = EncryptionPair(
        CryptoString(r'CURVE25519:mO?WWA-k2B2O|Z%fA`~s3^$iiN{5R->#jxO@cy6{'),
        CryptoString(r'CURVE25519:2bLf2vMA?GA2?L~tv<PA9XOw6e}V~ObNi7C&qek>'))
    status = serverconn.regcode(conn, 'admin', dbdata['admin_regcode'],
                                password.hashstring, devid, keypair, '')
    assert not status.error(
    ), f"test_reset_password(): regcode failed: {status.info()}"

    status = serverconn.login(conn, dbdata['admin_wid'],
                              CryptoString(dbdata['oekey']))
    assert not status.error(
    ), f"test_reset_password(): login phase failed: {status.info()}"

    status = serverconn.password(conn, dbdata['admin_wid'],
                                 password.hashstring)
    assert not status.error(
    ), f"test_reset_password(): password phase failed: {status.info()}"

    status = serverconn.device(conn, devid, keypair)
    assert not status.error(), "test_reset_password(): device phase failed: " \
     f"{status.info()}"

    status = init_user(conn, dbdata)
    assert not status.error(
    ), f"test_reset_password(): user init failed: {status.info()}"

    status = serverconn.reset_password(conn, dbdata['user_wid'])
    assert not status.error(
    ), f"test_reset_password(): password reset failed: {status.info()}"
    resetdata = status

    status = serverconn.logout(conn)
    assert not status.error(
    ), f"test_reset_password(): admin logout failed: {status.info()}"

    newpassword = Password('SomeOth3rPassw*rd')
    status = serverconn.passcode(conn, dbdata['user_wid'],
                                 resetdata['resetcode'],
                                 newpassword.hashstring)
    assert not status.error(
    ), f"test_reset_password(): passcode failed: {status.info()}"
示例#4
0
def test_preregister_regcode():
    '''Test the preregister and regcode commands'''
    dbconn = setup_test()
    dbdata = init_server(dbconn)

    conn = serverconn.ServerConnection()
    status = conn.connect('localhost', 2001)
    assert not status.error(
    ), f"test_login(): failed to connect to server: {status.info()}"

    password = Password('Linguini2Pegboard*Album')
    devid = '14142135-9c22-4d3e-84a3-2aa281f65714'
    keypair = EncryptionPair(
        CryptoString(r'CURVE25519:mO?WWA-k2B2O|Z%fA`~s3^$iiN{5R->#jxO@cy6{'),
        CryptoString(r'CURVE25519:2bLf2vMA?GA2?L~tv<PA9XOw6e}V~ObNi7C&qek>'))
    status = serverconn.regcode(conn, 'admin', dbdata['admin_regcode'],
                                password.hashstring, devid, keypair, '')
    assert not status.error(
    ), f"test_preregister_regcode(): regcode failed: {status.info()}"

    status = serverconn.login(conn, dbdata['admin_wid'],
                              CryptoString(dbdata['oekey']))
    assert not status.error(
    ), f"test_preregister_regcode(): login phase failed: {status.info()}"

    status = serverconn.password(conn, dbdata['admin_wid'],
                                 password.hashstring)
    assert not status.error(
    ), f"test_preregister_regcode(): password phase failed: {status.info()}"

    status = serverconn.device(conn, devid, keypair)
    assert not status.error(), "test_preregister_regcode(): device phase failed: " \
     f"{status.info()}"

    status = serverconn.preregister(conn, '', 'csimons', 'example.net')
    assert not status.error(
    ), "test_preregister_regcode(): uid preregistration failed"
    assert status['domain'] == 'example.net' and 'wid' in status and 'regcode' in status and \
     status['uid'] == 'csimons', "test_preregister_regcode(): failed to return expected data"

    regdata = status
    password = Password('MyS3cretPassw*rd')
    devpair = EncryptionPair()
    status = serverconn.regcode(conn, 'csimons', regdata['regcode'],
                                password.hashstring,
                                '11111111-1111-1111-1111-111111111111',
                                devpair, 'example.net')
    assert not status.error(), "test_preregister_regcode(): uid regcode failed"

    conn.disconnect()
示例#5
0
def keycard_admin(config, conn) -> dict:
    '''Uploads a keycard entry for the admin account'''

    conn = serverconn.ServerConnection()
    status = conn.connect('localhost', 2001)
    assert not status.error(
    ), f"test_addentry(): failed to connect to server: {status.info()}"

    crepair = EncryptionPair(
        CryptoString(r'CURVE25519:mO?WWA-k2B2O|Z%fA`~s3^$iiN{5R->#jxO@cy6{'),
        CryptoString(r'CURVE25519:2bLf2vMA?GA2?L~tv<PA9XOw6e}V~ObNi7C&qek>'))

    crspair = SigningPair(
        CryptoString(r'ED25519:E?_z~5@+tkQz!iXK?oV<Zx(ec;=27C8Pjm((kRc|'),
        CryptoString(r'ED25519:u4#h6LEwM6Aa+f<++?lma4Iy63^}V$JOP~ejYkB;'))

    epair = EncryptionPair(
        CryptoString(r'CURVE25519:Umbw0Y<^cf1DN|>X38HCZO@Je(zSe6crC6X_C_0F'),
        CryptoString(r'CURVE25519:Bw`F@ITv#sE)2NnngXWm7RQkxg{TYhZQbebcF5b$'))

    entry = keycard.UserEntry()
    entry.set_fields({
        'Name':
        'Administrator',
        'Workspace-ID':
        config['admin_wid'],
        'User-ID':
        'admin',
        'Domain':
        'example.com',
        'Contact-Request-Verification-Key':
        crspair.get_public_key(),
        'Contact-Request-Encryption-Key':
        crepair.get_public_key(),
        'Public-Encryption-Key':
        epair.get_public_key()
    })

    status = serverconn.addentry(conn, entry, CryptoString(config['ovkey']),
                                 crspair)
    assert not status.error(
    ), f"test_addentry: failed to add entry: {status.info()}"

    return {
        'admin_crepair': crepair,
        'admin_crspair': crspair,
        'admin_epair': epair
    }
示例#6
0
def test_addentry():
    '''Tests the addentry() command'''
    dbconn = setup_test()
    dbdata = init_server(dbconn)

    conn = serverconn.ServerConnection()
    status = conn.connect('localhost', 2001)
    assert not status.error(
    ), f"test_addentry(): failed to connect to server: {status.info()}"

    # Moved all the test code to integration_setup.init_admin(), because that kind of setup is
    # needed for other tests.
    status = init_admin(conn, dbdata)
    assert not status.error(
    ), f"test_addentry(): init_admin failed: {status.info()}"

    conn.disconnect()
示例#7
0
def test_iscurrent():
    '''Tests the iscurrent() command'''

    dbconn = setup_test()
    init_server(dbconn)

    conn = serverconn.ServerConnection()
    status = conn.connect('localhost', 2001)
    assert not status.error(
    ), f"test_login(): failed to connect to server: {status.info()}"

    status = serverconn.iscurrent(conn, 1)
    assert not status.error(
    ), f"test_iscurrent(): org failure check failed: {status.info()}"

    status = serverconn.iscurrent(conn, 2)
    assert not status.error(
    ), f"test_iscurrent(): org success check failed: {status.info()}"
示例#8
0
def test_unregister():
    '''Tests the unregister() command'''
    dbconn = setup_test()
    dbdata = init_server(dbconn)

    conn = serverconn.ServerConnection()
    status = conn.connect('localhost', 2001)
    assert not status.error(
    ), f"test_unregister(): failed to connect to server: {status.info()}"

    status = init_admin(conn, dbdata)
    assert not status.error(
    ), f"test_unregister(): init_admin failed: {status.info()}"

    status = init_user(conn, dbdata)
    assert not status.error(
    ), f"test_unregister(): init_user failed: {status.info()}"

    status = serverconn.logout(conn)
    assert not status.error(
    ), f"test_unregister(): logout failed: {status.info()}"

    status = serverconn.login(conn, dbdata['user_wid'],
                              CryptoString(dbdata['oekey']))
    assert not status.error(
    ), f"test_unregister(): user login phase failed: {status.info()}"

    status = serverconn.password(conn, dbdata['user_wid'],
                                 dbdata['user_password'].hashstring)
    assert not status.error(
    ), f"test_unregister(): password phase failed: {status.info()}"

    status = serverconn.device(conn, dbdata['user_devid'],
                               dbdata['user_devpair'])
    assert not status.error(
    ), f"test_unregister(): device phase failed: {status.info()}"

    status = serverconn.unregister(conn, dbdata['user_password'].hashstring,
                                   '')
    assert not status.error(
    ), f"test_unregister(): unregister failed: {status.info()}"

    conn.disconnect()
示例#9
0
def test_getwid():
    '''Tests serverconn.getwid(), which returns a WID for an Anselus address'''

    dbconn = setup_test()
    dbdata = init_server(dbconn)

    conn = serverconn.ServerConnection()
    status = conn.connect('localhost', 2001)
    assert not status.error(
    ), f"test_getwid(): failed to connect to server: {status.info()}"

    status = init_admin(conn, dbdata)
    assert not status.error(
    ), f"test_getwid(): init_admin failed: {status.info()}"

    status = serverconn.getwid(conn, 'admin', 'example.com')
    assert not status.error(), f"test_getwid(): getwid failed: {status.info()}"
    assert status['Workspace-ID'] == dbdata[
        'admin_wid'], "test_getwid(): admin wid mismatch"

    conn.disconnect()
示例#10
0
def test_overflow():
    '''Tests the server's command handling for commands greater than 8K'''

    dbconn = setup_test()
    dbdata = init_server(dbconn)
    conn = serverconn.ServerConnection()
    assert conn.connect('localhost',
                        2001), "Connection to server at localhost:2001 failed"

    # password is 'SandstoneAgendaTricycle'
    pwhash = '$argon2id$v=19$m=65536,t=2,p=1$ew5lqHA5z38za+257DmnTA$0LWVrI2r7XCq' \
       'dcCYkJLok65qussSyhN5TTZP+OTgzEI'
    devid = '22222222-2222-2222-2222-222222222222'
    devpair = EncryptionPair(
        CryptoString(r'CURVE25519:@X~msiMmBq0nsNnn0%~x{M|NU_{?<Wj)cYybdh&Z'),
        CryptoString(r'CURVE25519:W30{oJ?w~NBbj{F8Ag4~<bcWy6_uQ{i{X?NDq4^l'))

    dbdata['pwhash'] = pwhash
    dbdata['devid'] = devid
    dbdata['devpair'] = devpair

    regcode_admin(dbdata, conn)
    login_admin(dbdata, conn)

    conn.send_message({
        'Action': "REGISTER",
        'Data': {
            'Workspace-ID': 'A' * 10240,
            'Password-Hash': pwhash,
            'Device-ID': '11111111-1111-1111-1111-111111111111',
            'Device-Key': 'CURVE25519:@X~msiMmBq0nsNnn0%~x{M|NU_{?<Wj)cYybdh&Z'
        }
    })

    response = conn.read_response(server_response)
    assert response['Code'] == 400 and response['Status'] == 'BAD REQUEST', \
     'test_overflow: failed to catch overflow'

    conn.send_message({'Action': "QUIT"})
示例#11
0
def test_set_status():
    '''Test the SETSTATUS command'''
    dbconn = setup_test()
    dbdata = init_server(dbconn)

    conn = serverconn.ServerConnection()
    status = conn.connect('localhost', 2001)
    assert not status.error(
    ), f"test_set_workstatus(): failed to connect to server: {status.info()}"

    status = init_admin(conn, dbdata)
    assert not status.error(
    ), f"test_set_workstatus(): init_admin failed: {status.info()}"

    status = init_user(conn, dbdata)
    assert not status.error(
    ), f"test_set_workstatus(): init_user failed: {status.info()}"

    status = serverconn.setstatus(conn, dbdata['user_wid'], 'disabled')
    assert not status.error(
    ), f"test_set_workstatus(): set_workstatus failed: {status.info()}"

    conn.disconnect()
示例#12
0
def test_devkey():
    '''Tests the devkey() command'''
    dbconn = setup_test()
    dbdata = init_server(dbconn)

    conn = serverconn.ServerConnection()
    status = conn.connect('localhost', 2001)
    assert not status.error(
    ), f"test_devkey(): failed to connect to server: {status.info()}"

    status = init_admin(conn, dbdata)
    assert not status.error(
    ), f"test_devkey(): init_admin failed: {status.info()}"

    newdevpair = EncryptionPair(
        CryptoString(r'CURVE25519:mO?WWA-k2B2O|Z%fA`~s3^$iiN{5R->#jxO@cy6{'),
        CryptoString(r'CURVE25519:2bLf2vMA?GA2?L~tv<PA9XOw6e}V~ObNi7C&qek>'))

    status = serverconn.devkey(conn, dbdata['admin_devid'],
                               dbdata['admin_devpair'], newdevpair)
    assert not status.error(
    ), f"test_devkey(): error returned: {status.info()}"

    conn.disconnect()
示例#13
0
def test_register():
    '''Test worskpace registration'''

    # Registration testing only works when the server uses either network or public mode
    serverdbdata = load_server_config_file()
    if serverdbdata['global']['registration'] not in ['network', 'public']:
        return

    dbconn = setup_test()
    init_server(dbconn)

    conn = serverconn.ServerConnection()
    status = conn.connect('localhost', 2001)
    assert not status.error(
    ), f"test_login(): failed to connect to server: {status.info()}"

    password = Password('MyS3cretPassw*rd')
    devpair = EncryptionPair()
    status = serverconn.register(conn, 'csimons', password.hashstring,
                                 devpair.public)
    assert not status.error(
    ), f"test_register: failed to register test account: {status.info()}"

    conn.disconnect()
示例#14
0
def test_unregister():
    '''Test the UNREGISTER command'''

    # Testing the UNREGISTER command only works when the server uses either network or public mode
    serverconfig = load_server_config_file()
    if serverconfig['global']['registration'] not in ['network', 'public']:
        return

    dbconn = setup_test()
    dbdata = init_server(dbconn)
    conn = serverconn.ServerConnection()
    assert conn.connect('localhost',
                        2001), "Connection to server at localhost:2001 failed"

    # password is 'SandstoneAgendaTricycle'
    pwhash = '$argon2id$v=19$m=65536,t=2,p=1$ew5lqHA5z38za+257DmnTA$0LWVrI2r7XCq' \
       'dcCYkJLok65qussSyhN5TTZP+OTgzEI'
    devid = '22222222-2222-2222-2222-222222222222'
    devpair = EncryptionPair(
        CryptoString(r'CURVE25519:@X~msiMmBq0nsNnn0%~x{M|NU_{?<Wj)cYybdh&Z'),
        CryptoString(r'CURVE25519:W30{oJ?w~NBbj{F8Ag4~<bcWy6_uQ{i{X?NDq4^l'))

    dbdata['pwhash'] = pwhash
    dbdata['devid'] = devid
    dbdata['devpair'] = devpair

    regcode_admin(dbdata, conn)
    login_admin(dbdata, conn)

    userwid = '11111111-1111-1111-1111-111111111111'
    # password is 'SandstoneAgendaTricycle'
    pwhash = '$argon2id$v=19$m=65536,t=2,p=1$ew5lqHA5z38za+257DmnTA$0LWVrI2r7XCq' \
       'dcCYkJLok65qussSyhN5TTZP+OTgzEI'
    devkey = 'CURVE25519:@X~msiMmBq0nsNnn0%~x{M|NU_{?<Wj)cYybdh&Z'

    conn.send_message({
        'Action': "REGISTER",
        'Data': {
            'Workspace-ID': userwid,
            'Password-Hash': pwhash,
            'Device-ID': devid,
            'Device-Key': devkey
        }
    })

    response = conn.read_response(server_response)
    assert response['Code'] == 201 and response['Status'] == 'REGISTERED', \
     f"test_unregister: test user registration failed: {response['Status']}"

    # Subtest #1: Try to unregister the admin account
    conn.send_message({
        'Action': "UNREGISTER",
        'Data': {
            'Password-Hash': pwhash
        }
    })
    response = conn.read_response(server_response)
    assert response['Code'] == 403 and response['Status'] == 'FORBIDDEN', \
     "test_unregister(): failed to properly handle trying to unregister admin account"

    conn.send_message({'Action': "LOGOUT", 'Data': {}})
    response = conn.read_response(server_response)
    assert response['Code'] == 200 and response['Status'] == 'OK'

    # Set up for subtest #2: log in as the user
    status = serverconn.login(conn, userwid, CryptoString(dbdata['oekey']))
    assert not status.error(
    ), f"test_unregister(): user login phase failed: {status.info()}"

    status = serverconn.password(conn, userwid, pwhash)
    assert not status.error(
    ), f"test_unregister(): password phase failed: {status.info()}"

    status = serverconn.device(conn, devid, devpair)
    assert not status.error(
    ), f"test_unregister(): device phase failed: {status.info()}"

    # As a general rule, these anselusd integration tests don't call the regular pyanselus client
    # library calls because we do extra validation. However, we're going to make an exception in
    # this test because LOGIN and ADDENTRY are both really big.
    usercard = keycard.UserEntry()
    usercard.set_fields({
        'Name':
        'Corbin Simons',
        'Workspace-ID':
        userwid,
        'User-ID':
        'csimons',
        'Domain':
        'example.com',
        'Contact-Request-Verification-Key':
        'ED25519:E?_z~5@+tkQz!iXK?oV<Zx(ec;=27C8Pjm((kRc|',
        'Contact-Request-Encryption-Key':
        'CURVE25519:yBZ0{1fE9{2<b~#i^R+JT-yh-y5M(Wyw_)}_SZOn',
        'Public-Encryption-Key':
        'CURVE25519:_`UC|vltn_%P5}~vwV^)oY){#uvQSSy(dOD_l(yE'
    })

    crspair = SigningPair(
        CryptoString(r'ED25519:E?_z~5@+tkQz!iXK?oV<Zx(ec;=27C8Pjm((kRc|'),
        CryptoString(r'ED25519:u4#h6LEwM6Aa+f<++?lma4Iy63^}V$JOP~ejYkB;'))

    status = usercard.is_data_compliant()
    assert not status.error(
    ), f"test_unregister: user card not compliant: {status.info()}"
    status = serverconn.addentry(conn, usercard, CryptoString(dbdata['ovkey']),
                                 crspair)
    assert not status.error(), f"test_unregister: addentry() failed: {status.info()}\n" \
     f"Server Info: {status['Info']}"

    # Subtest #2: Unregister regular user from admin account
    conn.send_message({
        'Action': "UNREGISTER",
        'Data': {
            'Workspace-ID': userwid,
            'Password-Hash': pwhash
        }
    })

    response = conn.read_response(server_response)
    assert response['Code'] == 202 and response['Status'] == 'UNREGISTERED', \
     f"test_unregister(): user unregistration failed: {response['Status']}"

    # Check to make sure the database end was handled correctly
    cur = dbconn.cursor()
    cur.execute('SELECT password,status FROM workspaces WHERE wid = %s ',
                (userwid, ))
    row = cur.fetchone()
    assert row, "test_unregister(): cleanup check query found no rows"
    assert row[0] == '-' and row[1] == 'deleted', \
     "test_unregister(): server failed to clean up database properly"

    conn.send_message({'Action': "QUIT"})
示例#15
0
def test_register_failures():
    '''Tests the server's REGISTER command with failure conditions'''

    # Testing the REGISTER command only works when the server uses either network or public mode
    serverconfig = load_server_config_file()
    if serverconfig['global']['registration'] not in ['network', 'public']:
        return

    dbconn = setup_test()
    dbdata = init_server(dbconn)
    conn = serverconn.ServerConnection()
    assert conn.connect('localhost',
                        2001), "Connection to server at localhost:2001 failed"

    # password is 'SandstoneAgendaTricycle'
    pwhash = '$argon2id$v=19$m=65536,t=2,p=1$ew5lqHA5z38za+257DmnTA$0LWVrI2r7XCq' \
       'dcCYkJLok65qussSyhN5TTZP+OTgzEI'
    devid = '22222222-2222-2222-2222-222222222222'
    devpair = EncryptionPair(
        CryptoString(r'CURVE25519:@X~msiMmBq0nsNnn0%~x{M|NU_{?<Wj)cYybdh&Z'),
        CryptoString(r'CURVE25519:W30{oJ?w~NBbj{F8Ag4~<bcWy6_uQ{i{X?NDq4^l'))

    dbdata['pwhash'] = pwhash
    dbdata['devid'] = devid
    dbdata['devpair'] = devpair

    regcode_admin(dbdata, conn)
    login_admin(dbdata, conn)

    # Test #1: Attempt registration with unsupported encryption type

    conn.send_message({
        'Action': "REGISTER",
        'Data': {
            'Workspace-ID': '11111111-1111-1111-1111-222222222222',
            'Password-Hash': pwhash,
            'Device-ID': '11111111-1111-1111-1111-111111111111',
            'Device-Key': '3DES:@X~msiMmBq0nsNnn0%~x{M|NU_{?<Wj)cYybdh&Z'
        }
    })

    response = conn.read_response(server_response)
    assert response['Code'] == 309 and response['Status'] == 'ENCRYPTION TYPE NOT SUPPORTED', \
     'test_register_failures: subtest #1 failed to catch unsupported encryption'

    # Test #2: Send bad WID

    conn.send_message({
        'Action': "REGISTER",
        'Data': {
            'Workspace-ID':
            'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
            'Password-Hash': pwhash,
            'Device-ID': '11111111-1111-1111-1111-111111111111',
            'Device-Key': 'CURVE25519:@X~msiMmBq0nsNnn0%~x{M|NU_{?<Wj)cYybdh&Z'
        }
    })

    response = conn.read_response(server_response)
    assert response['Code'] == 400 and response['Status'] == 'BAD REQUEST', \
     'test_register_failures: subtest #2 failed to catch a bad WID'

    conn.send_message({'Action': "QUIT"})
示例#16
0
 def __init__(self):
     self.fs = ClientStorage()
     self.active_profile = ''
     self.conn = serverconn.ServerConnection()
示例#17
0
def test_register():
    '''Tests the server's REGISTER command - success and duplicate WID condition'''

    # Testing the REGISTER command only works when the server uses either network or public mode
    serverconfig = load_server_config_file()
    if serverconfig['global']['registration'] not in ['network', 'public']:
        return

    dbconn = setup_test()
    dbdata = init_server(dbconn)
    conn = serverconn.ServerConnection()
    assert conn.connect('localhost',
                        2001), "Connection to server at localhost:2001 failed"

    # password is 'SandstoneAgendaTricycle'
    pwhash = '$argon2id$v=19$m=65536,t=2,p=1$ew5lqHA5z38za+257DmnTA$0LWVrI2r7XCq' \
       'dcCYkJLok65qussSyhN5TTZP+OTgzEI'
    devid = '22222222-2222-2222-2222-222222222222'
    devpair = EncryptionPair(
        CryptoString(r'CURVE25519:@X~msiMmBq0nsNnn0%~x{M|NU_{?<Wj)cYybdh&Z'),
        CryptoString(r'CURVE25519:W30{oJ?w~NBbj{F8Ag4~<bcWy6_uQ{i{X?NDq4^l'))

    dbdata['pwhash'] = pwhash
    dbdata['devid'] = devid
    dbdata['devpair'] = devpair

    regcode_admin(dbdata, conn)
    login_admin(dbdata, conn)

    wid = '11111111-1111-1111-1111-111111111111'
    # password is 'SandstoneAgendaTricycle'
    pwhash = '$argon2id$v=19$m=65536,t=2,p=1$ew5lqHA5z38za+257DmnTA$0LWVrI2r7XCq' \
       'dcCYkJLok65qussSyhN5TTZP+OTgzEI'
    devkey = 'CURVE25519:@X~msiMmBq0nsNnn0%~x{M|NU_{?<Wj)cYybdh&Z'

    # Subtest #1: Regular registration that is supposed to succeed
    conn.send_message({
        'Action': "REGISTER",
        'Data': {
            'Workspace-ID': wid,
            'Password-Hash': pwhash,
            'Device-ID': '11111111-1111-1111-1111-111111111111',
            'Device-Key': devkey
        }
    })

    response = conn.read_response(server_response)
    assert response['Code'] == 201 and response['Status'] == 'REGISTERED', \
     'test_register: subtest #1 returned an error'

    # Subtest #2: Attempt registration of existing WID

    conn.send_message({
        'Action': "REGISTER",
        'Data': {
            'Workspace-ID': wid,
            'Password-Hash': pwhash,
            'Device-ID': '11111111-1111-1111-1111-111111111111',
            'Device-Key': devkey
        }
    })

    response = conn.read_response(server_response)
    assert response['Code'] == 408 and response['Status'] == 'RESOURCE EXISTS', \
     'test_register: subtest #2 failed to catch duplicate registration'

    conn.send_message({'Action': "QUIT"})