Files
Luma/Sources/Shared/XMPP/SaslFailureMessage.swift
T
wt fc07855036
iOS CI / Build and Test SwiftUI App (push) Canceled after 0s
Build Unsigned iOS and macOS Apps / Build Unsigned iOS IPA (push) Canceled after 0s
Build Unsigned iOS and macOS Apps / Build macOS ZIP (push) Canceled after 0s
#11 fix SASL login failures with non-ASCII passwords
- Normalize SCRAM passwords with RFC 4013 SASLprep before the
  challenge response, so they match SASLprep-compliant servers
  (Martin hashes raw UTF-8) and PLAIN still sends the password
  untouched.
- Capture the raw <failure/> condition with LumaSaslFailureModule and
  map SASL errors to actionable Russian messages instead of the
  cryptic OS-localized "Martin.SaslError, error 5".
- Cover SASLprep and failure message mapping with unit tests and new
  verify.sh invariants.
2026-08-29 01:26:03 +07:00

48 lines
2.6 KiB
Swift

import Foundation
import Martin
/// Turns a SASL authentication failure into an actionable Russian message.
/// The raw `<failure/>` condition (captured by `LumaSaslFailureModule`)
/// wins over Martin's `SaslError`, because Martin maps every unknown RFC
/// 6120 condition (e.g. `account-disabled`) to `not_authorized`.
enum SaslFailureMessage {
static func describe(error: Error, condition: String?, serverText: String?) -> String {
if let serverText, !serverText.isEmpty {
return "Сервер отклонил вход: \(serverText)"
}
switch condition {
case "account-disabled":
return "Аккаунт отключён на сервере. Обратитесь к администратору сервера."
case "credentials-expired":
return "Срок действия пароля истёк. Обновите пароль на сервере."
case "encryption-required":
return "Сервер требует шифрование канала для входа."
case "malformed-request":
return "Сервер не смог обработать запрос входа. Попробуйте ещё раз."
case "restricted-connection":
return "Сервер ограничил подключения с этого адреса."
default:
break
}
if let saslError = error as? SaslError {
switch saslError {
case .not_authorized:
return "Сервер отклонил имя пользователя или пароль. Проверьте JID и пароль."
case .temporary_auth_failure:
return "Сервер временно не может проверить учётные данные. Попробуйте через минуту."
case .server_not_trusted:
return "Сервер не прошёл проверку подписи SCRAM."
case .incorrect_encoding:
return "Сервер не принял кодировку учётных данных."
case .invalid_authzid:
return "Сервер отклонил идентификатор авторизации."
case .invalid_mechanism, .mechanism_too_weak:
return "Сервер не поддерживает доступные способы входа."
case .aborted:
return "Вход прерван."
}
}
return error.localizedDescription
}
}