diff --git a/client/Stream/Stream.gd b/client/Stream/Stream.gd index 4cfe7b6..e1cfc17 100644 --- a/client/Stream/Stream.gd +++ b/client/Stream/Stream.gd @@ -39,10 +39,40 @@ enum XMPPState { WAIT_TLS, # Wait TLS Done MISSING_TLS, # Missing feature TLS -> wait 30min and retry STARTED_TLS, # TLS connection is done + SELECT_MECHANISM_AUTHENTICATE, + AUTHENTICATE_STEP_PLAIN, # Select mechanism authenticate PLAIN AUTHENTICATE_STEP_1, # Launch authenticate AUTHENTICATE_STEP_2, # Launch authenticate AUTHENTICATE_STEP_3, # Launch authenticate + AUTHENTICATE_CHECK_RESULT, # Last time check result + AUTHENTICATE_FAILURE, + AUTHENTICATE_SUCCESS, AUTHENTICATED, # We finished authenticate + NOT_AUTHORIZED, # Not Authorize + ACCOUNT_DISABLED, # Account Disable +} + +enum ResultAuthenticate { + NONE, # Authenticate not started + DONE, # Authenticate finished and done + ABORT, # Authenticate finished with error (try other method) + NEXT, # Authenticate need execute other step +} + +enum SASLReturn { + SUCCESS, + ABORTED, + ACCOUNT_DISABLED, + CREDENTIALS_EXPIRED, + ENCRYPTION_REQUIRED, + INCORRECT_ENCODING, + INVALID_AUTHZID, + INVALID_MECHANISM, + MALFORMED_REQUEST, + MECHANISM_TOO_WEAK, + NOT_AUTHORIZED, + TEMPORARY_AUTH_FAILURE, + UNKNOWN } @export var server_xmpp_name:String = "localhost": @@ -98,6 +128,8 @@ func get_locale() -> String: const MAX_WAIT_CONNECTING:float = 60.0 const MAX_WAIT_MISSING_TLS:float = 1800.0 +const MAX_WAIT_ACCOUNT_DISABLED:float = 900.0 +const MAX_WAIT_NOT_AUTHORIZED:float = 18000.0 var try_connect:int = 0 var count_connecting_time:float = MAX_WAIT_CONNECTING @@ -108,6 +140,10 @@ var tgt_peer = null var status:StreamState = StreamState.END var xmpp_state = XMPPState.NONE var authentication_methods = [] +var selected_mechanism_authenticate:String = "" +var order_preference_mechanism_authenticate: Array = ['PLAIN'] +var banned_mechanism_authenticate:Array = [] + func reinit_stream(): if ssl_peer != null: @@ -140,6 +176,16 @@ func _process(delta) -> void: xmpp_state = XMPPState.NONE else: count_connecting_time += delta + elif xmpp_state == XMPPState.NOT_AUTHORIZED: + if count_connecting_time >= MAX_WAIT_NOT_AUTHORIZED: + xmpp_state = XMPPState.NONE + else: + count_connecting_time += delta + elif xmpp_state == XMPPState.ACCOUNT_DISABLED: + if count_connecting_time >= MAX_WAIT_ACCOUNT_DISABLED: + xmpp_state = XMPPState.NONE + else: + count_connecting_time += delta elif xmpp_state == XMPPState.NONE: if count_connecting_time >= MAX_WAIT_CONNECTING: xmpp_state = XMPPState.TRY_CONNECT_SERVER @@ -217,10 +263,14 @@ func _process(delta) -> void: else: count_connecting_time = 0 xmpp_state = XMPPState.MISSING_TLS - else: + elif response.begins_with("failure"): send_msg_error.emit(tr("TlS negotiation failed.")) count_connecting_time = 0 xmpp_state = XMPPState.MISSING_TLS + else: + send_msg_error.emit(tr("TlS negotiation failed. (unknow return)")) + count_connecting_time = 0 + xmpp_state = XMPPState.MISSING_TLS elif xmpp_state == XMPPState.WAIT_TLS: if tcp_peer.get_status() != StreamPeerTCP.STATUS_CONNECTED: xmpp_state = XMPPState.NONE @@ -264,18 +314,27 @@ func _process(delta) -> void: if analyze_feature_mechanisms(response): if authentication_methods.size() > 0: count_connecting_time = MAX_WAIT_CONNECTING - xmpp_state = XMPPState.AUTHENTICATE_STEP_1 + xmpp_state = XMPPState.SELECT_MECHANISM_AUTHENTICATE #send_msg_debug.emit("AUTHENTICATE_STEP_1") # elif response.begins_with("= MAX_WAIT_CONNECTING: count_connecting_time = 0 - negotiate_ssl_sasl(authentication_methods) + negotiate_ssl_authenticate_plain() else: count_connecting_time += delta if (ssl_peer.has_method("poll")): @@ -284,9 +343,59 @@ func _process(delta) -> void: var response = ssl_peer.get_string(ssl_peer.get_available_bytes()) send_msg_debug.emit("Stream: response: " + response) response = remove_stream_header(response) - if response.begins_with(" SASLReturn: + response = remove_stream_header(response) + if response.begins_with(""): + return SASLReturn.ABORTED + elif response.contains(""): + return SASLReturn.ACCOUNT_DISABLED + if response.contains(""): + return SASLReturn.CREDENTIALS_EXPIRED + if response.contains(""): + return SASLReturn.ENCRYPTION_REQUIRED + if response.contains(""): + return SASLReturn.INCORRECT_ENCODING + if response.contains(""): + return SASLReturn.INVALID_AUTHZID + if response.contains(""): + return SASLReturn.INVALID_MECHANISM + if response.contains(""): + return SASLReturn.MALFORMED_REQUEST + if response.contains(""): + return SASLReturn.MECHANISM_TOO_WEAK + if response.contains(""): + return SASLReturn.NOT_AUTHORIZED + if response.contains(""): + return SASLReturn.TEMPORARY_AUTH_FAILURE + return SASLReturn.UNKNOWN func analyze_error(response:String) -> bool: @@ -373,6 +482,32 @@ func send_ssl_initialize_xmpp() -> void: send_ssl_string(message) +func select_mechanism_authenticate(authentication_methods : Array) -> void: + selected_mechanism_authenticate = "NONE" + for item in order_preference_mechanism_authenticate: + if banned_mechanism_authenticate.has(item): + continue + elif authentication_methods.has(item): + selected_mechanism_authenticate = item + break + + +func negotiate_ssl_authenticate_plain() -> void: + send_msg_debug.emit("Stream: sending request for plain") + var msg:PackedByteArray = PackedByteArray() + msg.push_back(0) + var t = account_name.split("@")[0] + msg += t.to_ascii_buffer() + #msg += conv_string_to_PackedByteArray(account_name.split("@")[0]) + msg.push_back(0) + msg += password.to_ascii_buffer() + var auth_account:String = Marshalls.raw_to_base64(msg) + var request_sasl:String = "" + auth_account + "" + send_ssl_string(request_sasl) + func negotiate_ssl_sasl(authentication_methods : Array) -> bool: if ( authentication_methods.has("PLAIN")):