Hook up auth
This commit is contained in:
parent
08d2e8c4b4
commit
6f504dc71c
9 changed files with 69 additions and 30 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1130,6 +1130,7 @@ dependencies = [
|
||||||
"maplit",
|
"maplit",
|
||||||
"nom",
|
"nom",
|
||||||
"panorama-proto-common",
|
"panorama-proto-common",
|
||||||
|
"serde",
|
||||||
"stderrlog",
|
"stderrlog",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls 0.23.1",
|
"tokio-rustls 0.23.1",
|
||||||
|
|
|
@ -9,6 +9,7 @@ use std::io::Read;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use panorama_imap::client::auth::ImapAuth;
|
||||||
|
|
||||||
#[cfg(feature = "config-watch")]
|
#[cfg(feature = "config-watch")]
|
||||||
pub use self::watcher::{spawn_config_watcher_system, ConfigWatcher};
|
pub use self::watcher::{spawn_config_watcher_system, ConfigWatcher};
|
||||||
|
@ -62,21 +63,6 @@ pub struct ImapConfig {
|
||||||
pub auth: ImapAuth,
|
pub auth: ImapAuth,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Method of authentication for the IMAP server
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Derivative)]
|
|
||||||
#[derivative(Debug)]
|
|
||||||
#[serde(tag = "auth")]
|
|
||||||
pub enum ImapAuth {
|
|
||||||
/// Use plain username/password authentication
|
|
||||||
#[serde(rename = "plain")]
|
|
||||||
Plain {
|
|
||||||
username: String,
|
|
||||||
|
|
||||||
#[derivative(Debug = "ignore")]
|
|
||||||
password: String,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Describes when to perform the TLS handshake
|
/// Describes when to perform the TLS handshake
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub enum TlsMethod {
|
pub enum TlsMethod {
|
||||||
|
|
|
@ -49,9 +49,11 @@ pub async fn mail_main(
|
||||||
.tls(matches!(acct.imap.tls, TlsMethod::On))
|
.tls(matches!(acct.imap.tls, TlsMethod::On))
|
||||||
.build()?;
|
.build()?;
|
||||||
let pool_config = PoolConfig {
|
let pool_config = PoolConfig {
|
||||||
|
auth_config: acct.imap.auth,
|
||||||
|
client_config,
|
||||||
max_connections: 10,
|
max_connections: 10,
|
||||||
};
|
};
|
||||||
let pool = ImapPool::new(client_config, pool_config);
|
let pool = ImapPool::new(pool_config);
|
||||||
|
|
||||||
// grab one connection from that pool and start running a background
|
// grab one connection from that pool and start running a background
|
||||||
// synchronization thread
|
// synchronization thread
|
||||||
|
|
|
@ -13,8 +13,9 @@ readme = "README.md"
|
||||||
workspace = ".."
|
workspace = ".."
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["pool", "rfc2177", "rfc6154"]
|
default = ["serialize", "pool", "rfc2177", "rfc6154"]
|
||||||
low-level = []
|
low-level = []
|
||||||
|
serialize = ["serde/derive"]
|
||||||
pool = ["crossbeam"]
|
pool = ["crossbeam"]
|
||||||
rfc2087 = [] # quota
|
rfc2087 = [] # quota
|
||||||
rfc2177 = [] # idle
|
rfc2177 = [] # idle
|
||||||
|
@ -41,10 +42,12 @@ tokio-util = { version = "0.6.9", features = ["codec"] }
|
||||||
webpki-roots = "0.22.1"
|
webpki-roots = "0.22.1"
|
||||||
panorama-proto-common = { path = "../proto-common" }
|
panorama-proto-common = { path = "../proto-common" }
|
||||||
|
|
||||||
crossbeam = { version = "0.8.1", optional = true }
|
|
||||||
|
|
||||||
# for fuzzing
|
# for fuzzing
|
||||||
arbitrary = { version = "1.0.2", optional = true, features = ["derive"] }
|
arbitrary = { version = "1.0.2", optional = true, features = ["derive"] }
|
||||||
|
|
||||||
|
crossbeam = { version = "0.8.1", optional = true }
|
||||||
|
serde = { version = "1.0.130", optional = true }
|
||||||
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
maplit = "1.0.2"
|
maplit = "1.0.2"
|
||||||
|
|
|
@ -4,8 +4,46 @@ use anyhow::Result;
|
||||||
use panorama_proto_common::Bytes;
|
use panorama_proto_common::Bytes;
|
||||||
|
|
||||||
use crate::client::inner::Inner;
|
use crate::client::inner::Inner;
|
||||||
|
use crate::interface::ImapClient;
|
||||||
use crate::proto::command::{Command, CommandLogin};
|
use crate::proto::command::{Command, CommandLogin};
|
||||||
|
|
||||||
|
/// Method of authentication for the IMAP server
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "serialize",
|
||||||
|
derive(Serialize, Deserialize, Clone, Derivative)
|
||||||
|
)]
|
||||||
|
#[derivative(Debug)]
|
||||||
|
#[serde(tag = "auth")]
|
||||||
|
pub enum ImapAuth {
|
||||||
|
/// Use plain username/password authentication
|
||||||
|
#[serde(rename = "plain")]
|
||||||
|
Plain {
|
||||||
|
username: String,
|
||||||
|
|
||||||
|
#[derivative(Debug = "ignore")]
|
||||||
|
password: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ImapAuth {
|
||||||
|
pub async fn perform_auth<C>(&self, inner: &mut Inner<C>) -> Result<()>
|
||||||
|
where
|
||||||
|
C: Client,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
ImapAuth::Plain { username, password } => {
|
||||||
|
let command = Command::Login(CommandLogin {
|
||||||
|
userid: Bytes::from(username.clone()),
|
||||||
|
password: Bytes::from(password.clone()),
|
||||||
|
});
|
||||||
|
|
||||||
|
let result = inner.execute(command).await?;
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Client:
|
pub trait Client:
|
||||||
AsyncRead + AsyncWrite + Unpin + Sync + Send + 'static
|
AsyncRead + AsyncWrite + Unpin + Sync + Send + 'static
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,7 +22,7 @@ use crate::proto::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::auth::AuthMethod;
|
use super::auth::{AuthMethod, ImapAuth};
|
||||||
use super::inner::Inner;
|
use super::inner::Inner;
|
||||||
use super::response_stream::ResponseStream;
|
use super::response_stream::ResponseStream;
|
||||||
use super::tls::wrap_tls;
|
use super::tls::wrap_tls;
|
||||||
|
@ -102,10 +102,7 @@ impl ClientUnauthenticated {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn auth(
|
pub async fn auth(self, auth: &ImapAuth) -> Result<ClientAuthenticated> {
|
||||||
self,
|
|
||||||
auth: impl AuthMethod,
|
|
||||||
) -> Result<ClientAuthenticated> {
|
|
||||||
match self {
|
match self {
|
||||||
// this is a no-op, we don't need to upgrade
|
// this is a no-op, we don't need to upgrade
|
||||||
ClientUnauthenticated::Encrypted(mut inner) => {
|
ClientUnauthenticated::Encrypted(mut inner) => {
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use crate::proto::response::Envelope;
|
use crate::proto::{
|
||||||
|
command::Command,
|
||||||
|
response::{Envelope, Response},
|
||||||
|
};
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait ImapClient {
|
pub trait ImapClient {
|
||||||
|
|
|
@ -15,6 +15,10 @@ extern crate log;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate panorama_proto_common;
|
extern crate panorama_proto_common;
|
||||||
|
|
||||||
|
#[cfg(feature = "serialize")]
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate maplit;
|
extern crate maplit;
|
||||||
|
|
|
@ -4,7 +4,11 @@ use anyhow::Result;
|
||||||
use crossbeam::queue::ArrayQueue;
|
use crossbeam::queue::ArrayQueue;
|
||||||
use tokio::sync::Semaphore;
|
use tokio::sync::Semaphore;
|
||||||
|
|
||||||
use crate::{client::auth::{AuthMethod, Login}, interface::ImapClient, proto::response::Envelope};
|
use crate::{
|
||||||
|
client::auth::{ImapAuth, Login},
|
||||||
|
interface::ImapClient,
|
||||||
|
proto::response::Envelope,
|
||||||
|
};
|
||||||
|
|
||||||
use super::client::{ClientAuthenticated, Config, ConfigBuilder};
|
use super::client::{ClientAuthenticated, Config, ConfigBuilder};
|
||||||
|
|
||||||
|
@ -12,6 +16,7 @@ use super::client::{ClientAuthenticated, Config, ConfigBuilder};
|
||||||
pub struct PoolConfig {
|
pub struct PoolConfig {
|
||||||
pub max_connections: usize,
|
pub max_connections: usize,
|
||||||
pub client_config: Config,
|
pub client_config: Config,
|
||||||
|
pub auth_config: ImapAuth,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A pool of IMAP connections.
|
/// A pool of IMAP connections.
|
||||||
|
@ -49,10 +54,11 @@ pub struct InnerPool {
|
||||||
|
|
||||||
impl InnerPool {
|
impl InnerPool {
|
||||||
pub fn init(config: PoolConfig) -> Self {
|
pub fn init(config: PoolConfig) -> Self {
|
||||||
|
let max_connections = config.max_connections;
|
||||||
InnerPool {
|
InnerPool {
|
||||||
config,
|
config,
|
||||||
semaphore: Semaphore::new(config.max_connections),
|
semaphore: Semaphore::new(max_connections),
|
||||||
connections: ArrayQueue::new(config.max_connections),
|
connections: ArrayQueue::new(max_connections),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,8 +81,7 @@ impl InnerPool {
|
||||||
debug!("Client connected to {}", self.config.client_config.hostname);
|
debug!("Client connected to {}", self.config.client_config.hostname);
|
||||||
|
|
||||||
// authenticate
|
// authenticate
|
||||||
let client_auth = client.auth(Login {
|
let client_auth = client.auth(&self.config.auth_config);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue