mirror of
https://github.com/netbirdio/IronRDP.git
synced 2026-05-22 18:43:12 -07:00
refactor(web): add NegotiationFailure to IronErrorKind (#905)
Adds a general NegotiationFailure to IronErrorKind so that web embedders can handle failures that occur during protocol negotiation, before authentication. Changes: - RDP errors during the negotiation phase become IronErrorKind.NegotiationError - User-friendly RDP negotiation error messages to ironrdp-connector - Update TypeScript definitions
This commit is contained in:
@@ -21,4 +21,6 @@ pub enum IronErrorKind {
|
||||
RDCleanPath,
|
||||
/// Couldn’t connect to proxy
|
||||
ProxyConnect,
|
||||
/// Protocol negotiation failed
|
||||
NegotiationFailure,
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ use crate::channel_connection::{ChannelConnectionSequence, ChannelConnectionStat
|
||||
use crate::connection_activation::{ConnectionActivationSequence, ConnectionActivationState};
|
||||
use crate::license_exchange::{LicenseExchangeSequence, NoopLicenseCache};
|
||||
use crate::{
|
||||
encode_x224_packet, Config, ConnectorError, ConnectorErrorExt as _, ConnectorResult, DesktopSize, Sequence, State,
|
||||
Written,
|
||||
encode_x224_packet, Config, ConnectorError, ConnectorErrorExt as _, ConnectorErrorKind, ConnectorResult,
|
||||
DesktopSize, NegotiationFailure, Sequence, State, Written,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -274,7 +274,10 @@ impl Sequence for ClientConnector {
|
||||
nego::ConnectionConfirm::Response { flags, protocol } => (flags, protocol),
|
||||
nego::ConnectionConfirm::Failure { code } => {
|
||||
error!(?code, "Received connection failure code");
|
||||
return Err(reason_err!("Initiation", "{code}"));
|
||||
return Err(ConnectorError::new(
|
||||
"negotiation failure",
|
||||
ConnectorErrorKind::Negotiation(NegotiationFailure::from(code)),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -36,6 +36,55 @@ pub use self::license_exchange::{LicenseExchangeSequence, LicenseExchangeState};
|
||||
pub use self::server_name::ServerName;
|
||||
pub use crate::license_exchange::LicenseCache;
|
||||
|
||||
/// Provides user-friendly error messages for RDP negotiation failures
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct NegotiationFailure(ironrdp_pdu::nego::FailureCode);
|
||||
|
||||
impl NegotiationFailure {
|
||||
pub fn code(self) -> ironrdp_pdu::nego::FailureCode {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl core::error::Error for NegotiationFailure {}
|
||||
|
||||
impl From<ironrdp_pdu::nego::FailureCode> for NegotiationFailure {
|
||||
fn from(code: ironrdp_pdu::nego::FailureCode) -> Self {
|
||||
Self(code)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for NegotiationFailure {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use ironrdp_pdu::nego::FailureCode;
|
||||
|
||||
match self.0 {
|
||||
FailureCode::SSL_REQUIRED_BY_SERVER => {
|
||||
write!(f, "server requires Enhanced RDP Security with TLS or CredSSP")
|
||||
}
|
||||
FailureCode::SSL_NOT_ALLOWED_BY_SERVER => {
|
||||
write!(f, "server only supports Standard RDP Security")
|
||||
}
|
||||
FailureCode::SSL_CERT_NOT_ON_SERVER => {
|
||||
write!(f, "server lacks valid authentication certificate")
|
||||
}
|
||||
FailureCode::INCONSISTENT_FLAGS => {
|
||||
write!(f, "inconsistent security protocol flags")
|
||||
}
|
||||
FailureCode::HYBRID_REQUIRED_BY_SERVER => {
|
||||
write!(f, "server requires Enhanced RDP Security with CredSSP")
|
||||
}
|
||||
FailureCode::SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER => {
|
||||
write!(
|
||||
f,
|
||||
"server requires Enhanced RDP Security with TLS and client certificate"
|
||||
)
|
||||
}
|
||||
_ => write!(f, "unknown negotiation failure (code: 0x{:08x})", u32::from(self.0)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
pub struct DesktopSize {
|
||||
@@ -276,6 +325,7 @@ pub enum ConnectorErrorKind {
|
||||
AccessDenied,
|
||||
General,
|
||||
Custom,
|
||||
Negotiation(NegotiationFailure),
|
||||
}
|
||||
|
||||
impl fmt::Display for ConnectorErrorKind {
|
||||
@@ -288,6 +338,7 @@ impl fmt::Display for ConnectorErrorKind {
|
||||
ConnectorErrorKind::AccessDenied => write!(f, "access denied"),
|
||||
ConnectorErrorKind::General => write!(f, "general error"),
|
||||
ConnectorErrorKind::Custom => write!(f, "custom error"),
|
||||
ConnectorErrorKind::Negotiation(failure) => write!(f, "negotiation failure: {failure}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -302,6 +353,7 @@ impl core::error::Error for ConnectorErrorKind {
|
||||
ConnectorErrorKind::AccessDenied => None,
|
||||
ConnectorErrorKind::Custom => None,
|
||||
ConnectorErrorKind::General => None,
|
||||
ConnectorErrorKind::Negotiation(failure) => Some(failure),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ ironrdp = { path = "../ironrdp", features = [
|
||||
"cliprdr",
|
||||
"svc",
|
||||
"displaycontrol",
|
||||
"pdu",
|
||||
] }
|
||||
ironrdp-core.path = "../ironrdp-core"
|
||||
ironrdp-cliprdr-format.path = "../ironrdp-cliprdr-format"
|
||||
|
||||
@@ -37,6 +37,7 @@ impl From<connector::ConnectorError> for IronError {
|
||||
..
|
||||
}) => IronErrorKind::LogonFailure,
|
||||
ConnectorErrorKind::AccessDenied => IronErrorKind::AccessDenied,
|
||||
ConnectorErrorKind::Negotiation(_) => IronErrorKind::NegotiationFailure,
|
||||
_ => IronErrorKind::General,
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ export enum IronErrorKind {
|
||||
AccessDenied = 3,
|
||||
RDCleanPath = 4,
|
||||
ProxyConnect = 5,
|
||||
NegotiationFailure = 6,
|
||||
}
|
||||
|
||||
export interface IronError {
|
||||
|
||||
Reference in New Issue
Block a user