示例#1
0
def devkey(conn: ServerConnection, devid: str, oldpair: EncryptionPair, newpair: EncryptionPair):
	'''Replaces the specified device's key stored on the server'''
	if not utils.validate_uuid(devid):
		return RetVal(AnsBadRequest, 'Invalid device ID').set_value('status', 400)

	conn.send_message({
		'Action' : "DEVKEY",
		'Data' : { 
			'Device-ID': devid,
			'Old-Key': oldpair.public.as_string(),
			'New-Key': newpair.public.as_string()
		}
	})

	# Receive, decrypt, and return the server challenge
	response = conn.read_response(server_response)
	if response.error():
		return response
	
	if response['Code'] != 100:
		return wrap_server_error(response)

	if 'Challenge' not in response['Data'] or 'New-Challenge' not in response['Data']:
		return RetVal(ServerError, 'server did not return both device challenges')
	
	status = oldpair.decrypt(response['Data']['Challenge'])
	if status.error():
		cancel(conn)
		return RetVal(DecryptionFailure, 'failed to decrypt device challenge for old key')

	request = {
		'Action' : "DEVKEY",
		'Data' : { 
			'Response' : status['data']
		}
	}

	status = newpair.decrypt(response['Data']['New-Challenge'])
	if status.error():
		cancel(conn)
		return RetVal(DecryptionFailure, 'failed to decrypt device challenge for new key')
	request['Data']['New-Response'] = status['data']
	conn.send_message(request)

	response = conn.read_response(None)
	if response.error():
		return response
	
	if response['Code'] == 200:
		return RetVal()
	
	return wrap_server_error(response)
示例#2
0
def device(conn: ServerConnection, devid: str, devpair: EncryptionPair) -> RetVal:
	'''Completes the login process by submitting device ID and its session string.'''
	if not utils.validate_uuid(devid):
		return RetVal(AnsBadRequest, 'Invalid device ID').set_value('status', 400)

	conn.send_message({
		'Action' : "DEVICE",
		'Data' : { 
			'Device-ID' : devid,
			'Device-Key' : devpair.public.as_string()
		}
	})

	# Receive, decrypt, and return the server challenge
	response = conn.read_response(server_response)
	if response.error():
		return response
	
	if response['Code'] != 100:
		return wrap_server_error(response)

	if 'Challenge' not in response['Data']:
		return RetVal(ServerError, 'server did not return a device challenge')
	
	status = devpair.decrypt(response['Data']['Challenge'])
	if status.error():
		cancel(conn)
		return RetVal(DecryptionFailure, 'failed to decrypt device challenge')

	conn.send_message({
		'Action' : "DEVICE",
		'Data' : { 
			'Device-ID' : devid,
			'Device-Key' : devpair.public.as_string(),
			'Response' : status['data']
		}
	})

	response = conn.read_response(None)
	if response.error():
		return response
	
	if response['Code'] == 200:
		return RetVal()
	
	return wrap_server_error(response)
示例#3
0
def test_devkey():
    '''Tests the DEVKEY command'''
    dbconn = setup_test()
    dbdata = init_server(dbconn)
    conn = 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

    # Most of the code which was originally written for this test is needed for other tests
    # because commands like PREREG require being logged in as the administrator. Both of these
    # functions still perform all the necessary tests that were originally done here.
    regcode_admin(dbdata, conn)
    login_admin(dbdata, conn)

    newdevpair = EncryptionPair(
        CryptoString(r'CURVE25519:F0HjK;dB8tr<*2UkaHP?e1-tWAohWJ?IP+oP@o@C'),
        CryptoString(r'CURVE25519:|Cs(42=7FEwCoKG|5fVPC%MR6gD)_{h}}?ah%cIn'))

    conn.send_message({
        'Action': 'DEVKEY',
        'Data': {
            'Device-ID': devid,
            'Old-Key': dbdata['devpair'].get_public_key(),
            'New-Key': newdevpair.get_public_key()
        }
    })

    response = conn.read_response(None)
    assert response != 100 and response['Status'] == 'CONTINUE' and \
     'Challenge' in response['Data'] and 'New-Challenge' in response['Data'], \
     "test_devkey(): server failed to return new and old key challenge"

    msg = {'Action': "DEVKEY", 'Data': {}}

    status = devpair.decrypt(response['Data']['Challenge'])
    assert not status.error(
    ), 'login_devkey(): failed to decrypt device challenge for old key'
    msg['Data']['Response'] = status['data']

    status = newdevpair.decrypt(response['Data']['New-Challenge'])
    assert not status.error(
    ), 'login_devkey(): failed to decrypt device challenge for new key'
    msg['Data']['New-Response'] = status['data']

    conn.send_message(msg)

    response = conn.read_response(None)
    assert response['Code'] == 200 and response['Status'] == 'OK', \
     'Server challenge-response phase failed'

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