Exemple #1
0
	def process_login_request(self, data, client):
		if self.key is None:
			return b""
		
		stream = streams_nex.StreamIn(data, self.settings)
		ticket_data = stream.buffer()
		request_data = stream.buffer()
		
		ticket = kerberos.ServerTicket.decrypt(ticket_data, self.key, self.settings)
		if ticket.timestamp.timestamp() < time.time() - 120:
			raise ValueError("Ticket has expired")
		
		kerb = kerberos.KerberosEncryption(ticket.session_key)
		decrypted = kerb.decrypt(request_data)
		
		if len(decrypted) != self.settings["nex.pid_size"] + 8:
			raise ValueError("Invalid ticket size")
		
		stream = streams_nex.StreamIn(decrypted, self.settings)
		if stream.pid() != ticket.source:
			raise ValueError("Invalid pid in kerberos ticket")
		
		client.login(ticket.source, stream.u32(), ticket.session_key)
		
		check_value = stream.u32()
		return struct.pack("<II", 4, (check_value + 1) & 0xFFFFFFFF)
Exemple #2
0
	def login(self, username, password, auth_info=None, login_data=None):
		if auth_info:
			ticket = self.auth_client.login_ex(username, auth_info)
		else:
			ticket = self.auth_client.login(username)

		kerberos_key = self.key_derivation.derive_key(
			password.encode("ascii"), self.auth_client.pid
		)
		kerberos_encryption = kerberos.KerberosEncryption(kerberos_key)
		
		ticket.decrypt(kerberos_encryption, self.settings)
		
		if ticket.pid != self.auth_client.secure_station["PID"]:
			ticket = self.auth_client.request_ticket(
				self.auth_client.pid, self.auth_client.secure_station["PID"]
			)
			ticket.decrypt(kerberos_encryption, self.settings)

		host = self.auth_client.secure_station["address"]
		port = self.auth_client.secure_station["port"]
		if host == "0.0.0.1":
			host, port = self.auth_client.server_address()
		
		self.secure_client.set_ticket(ticket)
		self.secure_client.connect(host, port)
		if login_data:
			urls = self.secure_client.register_urls(login_data)
		else:
			urls = self.secure_client.register_urls()
		self.local_station, self.public_station = urls
Exemple #3
0
    def handle_connection_request(self, packet):
        logger.debug("Received connection request: %i bytes",
                     len(packet.payload))
        if not self.server_key:
            logger.debug("No validation needed, accepting connection")
            return b""

        if not packet.payload:
            logger.error("Received empty connection request for secure server")
            self.cleanup()
            return

        stream = streams.StreamIn(packet.payload, self.settings)
        ticket = stream.buffer()
        request = stream.buffer()

        server_ticket = kerberos.ServerTicket()
        try:
            server_ticket.decrypt(ticket, self.server_key, self.settings)
        except ValueError:
            logger.error("Server ticket decryption failed")
            self.cleanup()
            return

        if server_ticket.expiration.timestamp() < time.time():
            logger.error("Ticket has expired")
            self.cleanup()
            return

        kerb = kerberos.KerberosEncryption(server_ticket.session_key)
        try:
            decrypted = kerb.decrypt(request)
        except ValueError:
            logger.error("Ticket decryption failed")
            self.cleanup()
            return

        if len(decrypted) != self.settings.get("common.pid_size") + 8:
            logger.error("Invalid ticket size")
            self.cleanup()
            return

        stream = streams.StreamIn(decrypted, self.settings)
        if stream.pid() != server_ticket.source_pid:
            logger.error("Invalid pid in kerberos ticket")
            self.cleanup()
            return

        self.pid = server_ticket.source_pid

        stream.u32()  #Don't care about cid

        check_value = stream.u32()

        logger.debug("Connection request was validated successfully")
        self.set_session_key(server_ticket.session_key)

        return struct.pack("<II", 4, (check_value + 1) & 0xFFFFFFFF)
Exemple #4
0
    def __init__(self, backend, ticket):
        super().__init__(backend, service.ServiceClient.SECURE)
        self.ticket = ticket
        self.auth_client = backend.auth_client
        self.kerberos_encryption = kerberos.KerberosEncryption(self.ticket.key)

        station_url = self.auth_client.secure_station
        self.connection_id = station_url["CID"]
        self.principal_id = station_url["PID"]
Exemple #5
0
def test_kerberos_encryption():
    kerb = kerberos.KerberosEncryption(b"key")

    data = kerb.encrypt(b"test message")
    assert data == bytes.fromhex(
        "7f09479904e21e393b2a6f1ed5b96acc69a869dce66679d0cedb242d")
    assert kerb.check(data)
    assert not kerb.check(b"\x7e" + data[1:])
    assert kerb.decrypt(data) == b"test message"
Exemple #6
0
    def build_connection_request(self, ticket, check_value):
        stream = streams.StreamOut(self.settings)
        stream.buffer(ticket.internal)

        substream = streams.StreamOut(self.settings)
        substream.pid(ticket.source_pid)
        substream.u32(ticket.target_cid)
        substream.u32(check_value)

        kerb = kerberos.KerberosEncryption(ticket.session_key)
        stream.buffer(kerb.encrypt(substream.get()))
        return stream.get()
Exemple #7
0
	def build_connection_request(self):
		if self.credentials is None:
			return b""
		
		stream = streams_nex.StreamOut(self.settings)
		stream.buffer(self.credentials.ticket.internal)
		
		substream = streams_nex.StreamOut(self.settings)
		substream.pid(self.credentials.pid)
		substream.u32(self.credentials.cid)
		substream.u32(self.connection_check)
		
		kerb = kerberos.KerberosEncryption(self.credentials.ticket.session_key)
		stream.buffer(kerb.encrypt(substream.get()))
		return stream.get()
Exemple #8
0
    def build_connection_request(self):
        if not self.client_ticket:
            return b""

        self.check_value = random.randint(0, 0xFFFFFFFF)

        stream = streams.StreamOut(self.settings)
        stream.buffer(self.client_ticket.internal)

        substream = streams.StreamOut(self.settings)
        substream.pid(self.client_ticket.source_pid)
        substream.u32(self.client_ticket.target_cid)
        substream.u32(self.check_value)

        kerb = kerberos.KerberosEncryption(self.client_ticket.session_key)
        stream.buffer(kerb.encrypt(substream.get()))
        return stream.get()
Exemple #9
0
	def handle_login_result(self, call_id, password):
		stream = self.get_response(call_id)
		result = stream.u32()
		if result & 0x80000000:
			raise AuthenticationError("Login failed (%s)" %errors.error_names.get(result, "unknown error"))
			
		self.pid = stream.uint()
		kerberos_data = stream.buffer()
		self.secure_station = stream.extract(RVConnectionData).main_station
		server_name = stream.string()
		
		kerberos_key = self.key_derivation.derive_key(password.encode("ascii"), self.pid)
		self.kerberos_encryption = kerberos.KerberosEncryption(kerberos_key)
		if not self.kerberos_encryption.check_hmac(kerberos_data):
			raise AuthenticationError("Kerberos key validation failed (incorrect password)")

		logger.info("Authentication.login(_ex) -> (%08X, %s, %s)", self.pid, self.secure_station, server_name)
Exemple #10
0
    def validate_connection_request(self, payload):
        if not self.server_key or not payload:
            return True

        stream = streams.StreamIn(payload, self.settings)
        ticket = stream.buffer()
        request = stream.buffer()

        self.server_ticket = kerberos.ServerTicket()
        try:
            self.server_ticket.decrypt(ticket, self.server_key, self.settings)
        except ValueError:
            logger.error("Server ticket decryption failed")
            return False

        if self.server_ticket.expiration.timestamp() < time.time():
            logger.error("Ticket has expired")
            return False

        kerb = kerberos.KerberosEncryption(self.server_ticket.session_key)
        try:
            decrypted = kerb.decrypt(request)
        except ValueError:
            logger.error("Ticket decryption failed")
            return False

        self.set_session_key(self.server_ticket.session_key)

        if len(decrypted) != self.settings.get("common.pid_size") + 8:
            logger.error("Invalid ticket size")
            return False

        stream = streams.StreamIn(decrypted, self.settings)
        if stream.pid() != self.server_ticket.source_pid:
            logger.error("Invalid pid in kerberos ticket")
            return False

        stream.u32()  #Don't care about cid

        self.check_value = stream.u32()
        return True
    def connect(self, host, port):
        encryption = kerberos.KerberosEncryption(self.ticket.key)

        stream = streams.StreamOut(self.backend.settings)
        stream.buffer(self.ticket.data)

        check_value = random.randint(0, 0xFFFFFFFF)
        substream = streams.StreamOut(self.backend.settings)
        substream.uint(self.auth_client.pid)
        substream.u32(self.auth_client.secure_station["CID"])
        substream.u32(check_value)  #Used to check connection response

        stream.buffer(encryption.encrypt(substream.get()))
        response = super().connect(host, port, stream.get())

        stream = streams.StreamIn(response, self.backend.settings)
        if stream.u32() != 4:
            raise ConnectionError("Invalid connection response size")
        if stream.u32() != (check_value + 1) & 0xFFFFFFFF:
            raise ConnectionError("Connection response check failed")
        self.client.set_secure_key(self.ticket.key)
	def handle_connection_request(self, data):
		logger.debug("Received connection request: %i bytes", len(data))
		if not self.server_key:
			logger.debug("No validation needed, accepting connection")
			return b""
		
		if not data:
			raise ValueError("Received empty connection request on secure server")
		
		stream = streams_nex.StreamIn(data, self.settings)
		ticket_data = stream.buffer()
		request_data = stream.buffer()
		
		ticket = kerberos.ServerTicket.decrypt(ticket_data, self.server_key, self.settings)
		if ticket.timestamp.timestamp() < time.time() - 120:
			raise ValueError("Ticket has expired")
		
		kerb = kerberos.KerberosEncryption(ticket.session_key)
		decrypted = kerb.decrypt(request_data)
		
		if len(decrypted) != self.settings["nex.pid_size"] + 8:
			raise ValueError("Invalid ticket size")
		
		stream = streams_nex.StreamIn(decrypted, self.settings)
		if stream.pid() != ticket.source:
			raise ValueError("Invalid pid in kerberos ticket")
		
		self.user_pid = ticket.source
		self.user_cid = stream.u32()
		
		check_value = stream.u32()
		
		logger.debug("Connection request was validated successfully")
		self.set_session_key(ticket.session_key)
		
		return struct.pack("<II", 4, (check_value + 1) & 0xFFFFFFFF)