fakegreet: Dummy greetd backend

This commit is contained in:
Kenny Levinsen
2020-04-14 03:06:31 +02:00
parent 30135abc35
commit 6bcf82ad56
6 changed files with 315 additions and 1 deletions

51
Cargo.lock generated
View File

@@ -85,6 +85,16 @@ dependencies = [
"rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fakegreet"
version = "0.5.0"
dependencies = [
"greetd_ipc 0.5.1",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"thiserror 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fnv"
version = "1.0.6"
@@ -223,6 +233,17 @@ dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mio-named-pipes"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mio-uds"
version = "0.6.7"
@@ -244,6 +265,15 @@ dependencies = [
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "miow"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"socket2 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "net2"
version = "0.2.33"
@@ -363,6 +393,11 @@ dependencies = [
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rpassword"
version = "4.0.5"
@@ -428,6 +463,17 @@ name = "slab"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "socket2"
version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "1.0.14"
@@ -468,6 +514,7 @@ dependencies = [
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -578,8 +625,10 @@ dependencies = [
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
"checksum memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223"
"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f"
"checksum mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3"
"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125"
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226"
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
"checksum nix 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dd0eaf8df8bab402257e0a5c17a254e4cc1f72a93588a1ddfb5d356c801aa7cb"
"checksum nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363"
@@ -594,6 +643,7 @@ dependencies = [
"checksum rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
"checksum rpassword 4.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "99371657d3c8e4d816fb6221db98fa408242b0b53bac08f8676a41f8554fe99f"
"checksum rust-ini 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c609fa8151080b18c38d39e09d1e55d6301d5610428ff804d0d59c4bac15cf7"
"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
@@ -602,6 +652,7 @@ dependencies = [
"checksum serde_json 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "eab8f15f15d6c41a154c1b128a22f2dfabe350ef53c40953d84e36155c91192b"
"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
"checksum socket2 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918"
"checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
"checksum thiserror 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "205684fd018ca14432b12cce6ea3d46763311a571c3d294e71ba3f01adcf1aad"
"checksum thiserror-impl 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "57e4d2e50ca050ed44fb58309bdce3efa79948f84f9993ad1978de5eebdce5a7"

View File

@@ -9,4 +9,4 @@ incremental = false
codegen-units = 1
[workspace]
members = ["greetd_ipc", "greetd", "agreety"]
members = ["greetd_ipc", "greetd", "agreety", "fakegreet"]

2
fakegreet/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/target
**/*.rs.bk

14
fakegreet/Cargo.toml Normal file
View File

@@ -0,0 +1,14 @@
[package]
name = "fakegreet"
version = "0.5.0"
authors = ["Kenny Levinsen"]
edition = "2018"
license = "GPL-3.0"
homepage = "https://kl.wtf/projects/greetd"
repository = "https://git.sr.ht/~kennylevinsen/greetd/"
[dependencies]
serde = { version = "1.0", features = ["derive"] }
greetd_ipc = { path = "../greetd_ipc", features = ["tokio-codec"] }
tokio = { version = "0.2", features = ["process"] }
thiserror = "1.0"

56
fakegreet/src/error.rs Normal file
View File

@@ -0,0 +1,56 @@
use std::convert::From;
use serde::{Deserialize, Serialize};
use thiserror::Error as ThisError;
#[derive(Debug, ThisError, Clone, Deserialize, Serialize)]
pub enum Error {
#[error("{0}")]
Error(String),
#[error("authentication error: {0}")]
AuthError(String),
#[error("protocol error: {0}")]
ProtocolError(String),
#[error("i/o error: {0}")]
Io(String),
#[error("configuration error: {0}")]
ConfigError(String),
}
impl From<Box<dyn std::error::Error>> for Error {
fn from(error: Box<dyn std::error::Error>) -> Self {
Error::Error(format!("{}", error))
}
}
impl From<std::io::Error> for Error {
fn from(error: std::io::Error) -> Self {
Error::Io(format!("{}", error))
}
}
impl From<greetd_ipc::codec::Error> for Error {
fn from(error: greetd_ipc::codec::Error) -> Self {
match error {
greetd_ipc::codec::Error::Serialization(s) => Error::ProtocolError(s),
greetd_ipc::codec::Error::Io(s) => Error::Io(s),
greetd_ipc::codec::Error::Eof => Error::Io("EOF".to_string()),
}
}
}
impl From<String> for Error {
fn from(error: String) -> Self {
Error::Error(error)
}
}
impl From<&str> for Error {
fn from(error: &str) -> Self {
Error::Error(error.to_string())
}
}

191
fakegreet/src/main.rs Normal file
View File

@@ -0,0 +1,191 @@
mod error;
use std::{cell::RefCell, env, rc::Rc, time::Duration};
use tokio::{
net::{UnixListener, UnixStream},
process::Command,
task,
time::delay_for,
};
use crate::error::Error;
use greetd_ipc::{
codec::{Error as CodecError, TokioCodec},
AuthMessageType, ErrorType, Request, Response,
};
fn wrap_result<T>(res: Result<T, Error>) -> Response {
match res {
Ok(_) => Response::Success,
Err(Error::AuthError(msg)) => Response::Error {
error_type: ErrorType::AuthError,
description: msg,
},
Err(e) => Response::Error {
error_type: ErrorType::Error,
description: format!("{}", e),
},
}
}
struct InnerContext {
user: Option<String>,
password: Option<String>,
ok: bool,
}
struct Context {
inner: RefCell<InnerContext>,
}
impl Context {
fn new() -> Context {
Context {
inner: RefCell::new(InnerContext {
user: None,
password: None,
ok: false,
}),
}
}
async fn create_session(&self, username: String) -> Result<(), Error> {
self.inner.borrow_mut().user = Some(username);
Ok(())
}
async fn get_question(&self) -> Result<Option<(AuthMessageType, String)>, Error> {
let s = self.inner.borrow();
if s.ok {
Ok(None)
} else if s.user.is_none() {
Ok(Some((AuthMessageType::Visible, "User:".to_string())))
} else if s.password.is_none() {
Ok(Some((AuthMessageType::Secret, "Password:".to_string())))
} else {
Ok(Some((AuthMessageType::Visible, "7 + 2:".to_string())))
}
}
async fn post_response(&self, response: Option<String>) -> Result<(), Error> {
let mut s = self.inner.borrow_mut();
if s.ok {
return Err(Error::Error("wat".to_string()));
}
if s.user.is_none() {
s.user = response;
} else if s.password.is_none() {
s.password = response;
} else {
if s.user != Some("user".to_string())
|| s.password != Some("password".to_string())
|| response != Some("9".to_string())
{
delay_for(Duration::from_millis(2000)).await;
return Err(Error::AuthError("nope".to_string()));
}
s.ok = true;
}
Ok(())
}
async fn start(&self, _cmd: Vec<String>) -> Result<(), Error> {
if !self.inner.borrow().ok {
return Err(Error::Error("not yet dammit".to_string()));
}
delay_for(Duration::from_millis(5000)).await;
Ok(())
}
async fn cancel(&self) -> Result<(), Error> {
let mut s = self.inner.borrow_mut();
s.user = None;
s.password = None;
s.ok = false;
Ok(())
}
}
async fn client_get_question(ctx: &Context) -> Response {
match ctx.get_question().await {
Ok(Some((auth_message_type, auth_message))) => Response::AuthMessage {
auth_message_type,
auth_message,
},
res => wrap_result(res),
}
}
async fn client_handler(ctx: &Context, mut s: UnixStream) -> Result<(), Error> {
loop {
let req = match Request::read_from(&mut s).await {
Ok(req) => req,
Err(CodecError::Eof) => return Ok(()),
Err(e) => return Err(e.into()),
};
println!("req: {:?}", req);
let resp = match req {
Request::CreateSession { username } => match ctx.create_session(username).await {
Ok(()) => client_get_question(&ctx).await,
res => wrap_result(res),
},
Request::PostAuthMessageResponse { response } => {
match ctx.post_response(response).await {
Ok(()) => client_get_question(&ctx).await,
res => wrap_result(res),
}
}
Request::StartSession { cmd } => wrap_result(ctx.start(cmd).await),
Request::CancelSession => wrap_result(ctx.cancel().await),
};
println!("resp: {:?}", resp);
resp.write_to(&mut s).await?;
}
}
pub async fn server() -> Result<(), Error> {
let path = "./greetd.sock";
std::env::set_var("GREETD_SOCK", path);
let _ = std::fs::remove_file(path);
let mut listener =
UnixListener::bind(path).map_err(|e| format!("unable to open listener: {}", e))?;
let arg = env::args()
.skip(1)
.next()
.expect("need argument")
.to_string();
let _ = Command::new("sh").arg("-c").arg(arg).spawn()?;
let ctx = Rc::new(Context::new());
loop {
tokio::select! {
stream = listener.accept() => match stream {
Ok((stream, _)) => {
let ctx = ctx.clone();
task::spawn_local(async move {
if let Err(e) = client_handler(&ctx, stream).await {
eprintln!("client loop failed: {}", e);
}
});
},
Err(err) => return Err(format!("accept: {}", err).into()),
}
}
}
}
#[tokio::main]
async fn main() {
let res = task::LocalSet::new()
.run_until(async move { server().await })
.await;
if let Err(e) = res {
eprintln!("error: {}", e);
}
}