Skip to content

Commit

Permalink
Implement pizauth revoke.
Browse files Browse the repository at this point in the history
Currently this is local-only as OAuth2 provides no standard way of
revoking remote tokens (though some providers do provide ad-hoc
extensions to do so).
  • Loading branch information
ltratt committed Jan 2, 2024
1 parent d5920d4 commit 62b3c64
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 3 deletions.
9 changes: 9 additions & 0 deletions pizauth.1
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ See
.Sy dump
for information about the dump format, timestamp warnings, and encryption
suggestions.
.It Sy revoke Ar account
Removes any token, and cancels any ongoing authentication, for
.Em account .
Note that OAuth2 provides no standard way of remotely revoking a token:
.Sy revoke
thus only affects the local
.Nm
instance.
Exits with 0 upon success.
.It Sy server Oo Fl c Ar config-file Oc Oo Fl dv Oc
Start the server.
If not specified with
Expand Down
5 changes: 4 additions & 1 deletion pizauth.conf.5
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,10 @@ if a previously valid access token is invalidated;
.Em token_new
if a new access token is obtained;
.Em token_refreshed
if an access token is refreshed.
if an access token is refreshed;
.Em token_revoked
if the user has requested that any token, or ongoing authentication for,
an account should be removed or cancelled.
Token events are queued and processed one-by-one in the order they were
received: at most one instance of
.Sy token_event_cmd
Expand Down
17 changes: 16 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fn fatal(msg: &str) -> ! {
fn usage() -> ! {
let pn = progname();
eprintln!(
"Usage:\n {pn:} dump\n {pn:} info [-j]\n {pn:} refresh [-u] <account>\n {pn:} restore\n {pn:} reload\n {pn:} server [-c <config-path>] [-dv]\n {pn:} show [-u] <account>\n {pn:} shutdown\n {pn:} status"
"Usage:\n {pn:} dump\n {pn:} info [-j]\n {pn:} refresh [-u] <account>\n {pn:} restore\n {pn:} reload\n {pn:} revoke <account>\n {pn:} server [-c <config-path>] [-dv]\n {pn:} show [-u] <account>\n {pn:} shutdown\n {pn:} status"
);
process::exit(1)
}
Expand Down Expand Up @@ -223,6 +223,21 @@ fn main() {
process::exit(1);
}
}
"revoke" => {
let matches = opts.parse(&args[2..]).unwrap_or_else(|_| usage());
if matches.opt_present("h") || matches.free.len() != 1 {
usage();
}
stderrlog::new()
.module(module_path!())
.verbosity(matches.opt_count("v"))
.init()
.unwrap();
if let Err(e) = user_sender::revoke(&cache_path, &matches.free[0]) {
error!("{e:}");
process::exit(1);
}
}
"server" => {
let matches = opts
.optflagopt("c", "config", "Path to pizauth.conf.", "<conf-path>")
Expand Down
2 changes: 2 additions & 0 deletions src/server/eventer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub enum TokenEvent {
Invalidated,
New,
Refresh,
Revoked,
}

impl Display for TokenEvent {
Expand All @@ -29,6 +30,7 @@ impl Display for TokenEvent {
TokenEvent::Invalidated => write!(f, "token_invalidated"),
TokenEvent::New => write!(f, "token_new"),
TokenEvent::Refresh => write!(f, "token_refreshed"),
TokenEvent::Revoked => write!(f, "token_revoked"),
}
}
}
Expand Down
23 changes: 22 additions & 1 deletion src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use pledge::pledge;
use unveil::unveil;

use crate::{config::Config, PIZAUTH_CACHE_SOCK_LEAF};
use eventer::Eventer;
use eventer::{Eventer, TokenEvent};
use notifier::Notifier;
use refresher::Refresher;
use request_token::request_token;
Expand Down Expand Up @@ -130,6 +130,27 @@ fn request(pstate: Arc<AuthenticatorState>, mut stream: UnixStream) -> Result<()
}
return Ok(());
}
"revoke" => {
let act_name = std::str::from_utf8(rest)?;
let mut ct_lk = pstate.ct_lock();
match ct_lk.validate_act_name(act_name) {
Some(act_id) => {
ct_lk.tokenstate_replace(act_id, TokenState::Empty);
drop(ct_lk);

pstate
.eventer
.token_event(act_name.to_owned(), TokenEvent::Revoked);
stream.write_all(format!("ok:").as_bytes())?;
return Ok(());
}
None => {
drop(ct_lk);
stream.write_all(format!("error:No account '{act_name:}'").as_bytes())?;
return Ok(());
}
};
}
"showtoken" => {
let rest = std::str::from_utf8(rest)?;
if let [with_url, act_name] = &rest.splitn(2, ' ').collect::<Vec<_>>()[..] {
Expand Down
18 changes: 18 additions & 0 deletions src/user_sender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,24 @@ pub fn restore(cache_path: &Path) -> Result<(), Box<dyn Error>> {
}
}

pub fn revoke(cache_path: &Path, account: &str) -> Result<(), Box<dyn Error>> {
let sock_path = sock_path(cache_path);
let mut stream = UnixStream::connect(sock_path)
.map_err(|_| "pizauth authenticator not running or not responding")?;
stream
.write_all(format!("revoke:{account}").as_bytes())
.map_err(|_| "Socket not writeable")?;
stream.shutdown(Shutdown::Write)?;

let mut rtn = String::new();
stream.read_to_string(&mut rtn)?;
match rtn.splitn(2, ':').collect::<Vec<_>>()[..] {
["ok", ""] => Ok(()),
["error", cause] => Err(cause.into()),
_ => Err(format!("Malformed response '{rtn:}'").into()),
}
}

pub fn show_token(cache_path: &Path, account: &str, with_url: bool) -> Result<(), Box<dyn Error>> {
let sock_path = sock_path(cache_path);
let with_url = if with_url { "withurl" } else { "withouturl" };
Expand Down

0 comments on commit 62b3c64

Please sign in to comment.