From 9fb5bc41b4c71e4bc8878972a93013e78f4ebc5b Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Tue, 25 Jun 2024 14:56:46 +0300 Subject: [PATCH] melib/imap: impl AUTH=ANONYMOUS (RFC4505) Signed-off-by: Manos Pitsidianakis --- meli/docs/meli.1 | 8 ++++++++ meli/docs/meli.conf.5 | 6 ++++++ melib/src/imap/connection.rs | 27 +++++++++++++++++++++++++++ melib/src/imap/mod.rs | 13 +++++++++++++ 4 files changed, 54 insertions(+) diff --git a/meli/docs/meli.1 b/meli/docs/meli.1 index 4531484d..4179fef3 100644 --- a/meli/docs/meli.1 +++ b/meli/docs/meli.1 @@ -803,6 +803,14 @@ Mailcap entries are searched for in the following files, in this order: .Re .It .Rs +.%B RFC4505 Anonymous Simple Authentication and Security Layer (SASL) Mechanism +.%I IETF +.%D June 12, 2006 +.%A Kurt Zeilenga +.%U https://datatracker.ietf.org/doc/rfc4505/ +.Re +.It +.Rs .%B RFC4549 Synchronization Operations for Disconnected IMAP4 Clients .%I IETF .%D June 16, 2006 diff --git a/meli/docs/meli.conf.5 b/meli/docs/meli.conf.5 index fcd8b253..ad70a0ce 100644 --- a/meli/docs/meli.conf.5 +++ b/meli/docs/meli.conf.5 @@ -455,6 +455,12 @@ For help on setup with .Tn Gmail section below. .Pq Em false \" default value +.It Ic use_auth_anonymous Ar boolean +.Pq Em optional +Use +.Em AUTH=ANONYMOUS +extension for authentication. +.Pq Em false \" default value .It Ic timeout Ar integer .Pq Em optional Timeout to use for server connections in seconds. diff --git a/melib/src/imap/connection.rs b/melib/src/imap/connection.rs index c2a277dd..9914b4ce 100644 --- a/melib/src/imap/connection.rs +++ b/melib/src/imap/connection.rs @@ -94,7 +94,9 @@ pub enum ImapProtocol { } #[derive(Clone, Copy, Debug)] +#[non_exhaustive] pub struct ImapExtensionUse { + pub auth_anonymous: bool, pub condstore: bool, pub idle: bool, pub deflate: bool, @@ -104,6 +106,7 @@ pub struct ImapExtensionUse { impl Default for ImapExtensionUse { fn default() -> Self { Self { + auth_anonymous: false, condstore: true, idle: true, deflate: true, @@ -425,6 +428,29 @@ impl ImapStream { )) .await?; } + ImapProtocol::IMAP { + extension_use: ImapExtensionUse { auth_anonymous, .. }, + } if auth_anonymous => { + if !capabilities + .iter() + .any(|cap| cap.eq_ignore_ascii_case(b"AUTH=ANONYMOUS")) + { + return Err(Error::new(format!( + "Could not connect to {}: AUTH=ANONYMOUS is enabled but server did not \ + return AUTH=ANONYMOUS capability. Returned capabilities were: {}", + &server_conf.server_hostname, + capabilities + .iter() + .map(|capability| String::from_utf8_lossy(capability).to_string()) + .collect::>() + .join(" ") + )) + .set_kind(ErrorKind::Authentication)); + } + ret.send_command_raw(b"AUTHENTICATE ANONYMOUS").await?; + ret.wait_for_continuation_request().await?; + ret.send_literal(b"c2lyaGM=").await?; + } _ => { let username = AString::try_from(server_conf.server_username.as_str()) .chain_err_kind(ErrorKind::Bug)?; @@ -724,6 +750,7 @@ impl ImapConnection { deflate, idle: _idle, oauth2: _, + auth_anonymous: _, }, } => { if capabilities.contains(&b"CONDSTORE"[..]) && condstore { diff --git a/melib/src/imap/mod.rs b/melib/src/imap/mod.rs index ca95fb2d..c96c48be 100644 --- a/melib/src/imap/mod.rs +++ b/melib/src/imap/mod.rs @@ -79,6 +79,7 @@ pub type UIDVALIDITY = UID; pub type MessageSequenceNumber = ImapNum; pub static SUPPORTED_CAPABILITIES: &[&str] = &[ + "AUTH=ANONYMOUS", "AUTH=OAUTH2", "COMPRESS=DEFLATE", "CONDSTORE", @@ -257,6 +258,7 @@ impl MailBackend for ImapType { deflate, condstore, oauth2, + auth_anonymous, }, } = self.server_conf.protocol { @@ -298,6 +300,15 @@ impl MailBackend for ImapType { }; } } + "AUTH=ANONYMOUS" => { + if auth_anonymous { + *status = MailBackendExtensionStatus::Enabled { comment: None }; + } else { + *status = MailBackendExtensionStatus::Supported { + comment: Some("Disabled by user configuration"), + }; + } + } _ => { if SUPPORTED_CAPABILITIES .iter() @@ -1339,6 +1350,7 @@ impl ImapType { condstore: get_conf_val!(s["use_condstore"], true)?, deflate: get_conf_val!(s["use_deflate"], true)?, oauth2: use_oauth2, + auth_anonymous: get_conf_val!(s["use_auth_anonymous"], false)?, }, }, timeout, @@ -1608,6 +1620,7 @@ impl ImapType { get_conf_val!(s["use_idle"], true)?; get_conf_val!(s["use_condstore"], true)?; get_conf_val!(s["use_deflate"], true)?; + get_conf_val!(s["use_auth_anonymous"], false)?; let _timeout = get_conf_val!(s["timeout"], 16_u64)?; let extra_keys = s .extra