Restore the real ident when a HostServ ident@host vhost is turned off or deleted
This commit is contained in:
parent
384f222a22
commit
af5896743d
4 changed files with 35 additions and 2 deletions
|
|
@ -640,6 +640,13 @@ impl ServiceCtx {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_ident(&mut self, uid: &str, ident: &str) {
|
||||||
|
self.actions.push(NetAction::SetIdent {
|
||||||
|
uid: uid.to_string(),
|
||||||
|
ident: ident.to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Apply a vhost spec to a user: `ident@host` sets both the ident and host,
|
// Apply a vhost spec to a user: `ident@host` sets both the ident and host,
|
||||||
// a bare `host` just the host.
|
// a bare `host` just the host.
|
||||||
pub fn apply_vhost(&mut self, uid: &str, spec: &str) {
|
pub fn apply_vhost(&mut self, uid: &str, spec: &str) {
|
||||||
|
|
@ -2142,6 +2149,8 @@ pub trait NetView {
|
||||||
fn uid_by_nick(&self, nick: &str) -> Option<&str>;
|
fn uid_by_nick(&self, nick: &str) -> Option<&str>;
|
||||||
fn nick_of(&self, uid: &str) -> Option<&str>;
|
fn nick_of(&self, uid: &str) -> Option<&str>;
|
||||||
fn host_of(&self, uid: &str) -> Option<&str>;
|
fn host_of(&self, uid: &str) -> Option<&str>;
|
||||||
|
// A user's real ident (username), for restoring after an `ident@host` vhost.
|
||||||
|
fn ident_of(&self, uid: &str) -> Option<&str>;
|
||||||
fn account_of(&self, uid: &str) -> Option<&str>;
|
fn account_of(&self, uid: &str) -> Option<&str>;
|
||||||
// A user's identity for extban / AKICK matching, if known.
|
// A user's identity for extban / AKICK matching, if known.
|
||||||
fn ban_target(&self, uid: &str) -> Option<BanTarget<'_>>;
|
fn ban_target(&self, uid: &str) -> Option<BanTarget<'_>>;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,9 @@ pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, net:
|
||||||
ctx.notice(me, from.uid, "Syntax: DEL <account>");
|
ctx.notice(me, from.uid, "Syntax: DEL <account>");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
// Note whether the vhost spoofed the ident (`ident@host`) before removing it,
|
||||||
|
// so online sessions get their real ident back too, not just their host.
|
||||||
|
let had_ident = db.vhost(account).is_some_and(|v| v.host.contains('@'));
|
||||||
match db.del_vhost(account) {
|
match db.del_vhost(account) {
|
||||||
Ok(true) => {
|
Ok(true) => {
|
||||||
for uid in net.uids_logged_into(account) {
|
for uid in net.uids_logged_into(account) {
|
||||||
|
|
@ -17,6 +20,12 @@ pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, net:
|
||||||
let host = host.to_string();
|
let host = host.to_string();
|
||||||
ctx.set_host(&uid, &host);
|
ctx.set_host(&uid, &host);
|
||||||
}
|
}
|
||||||
|
if had_ident {
|
||||||
|
if let Some(ident) = net.ident_of(&uid) {
|
||||||
|
let ident = ident.to_string();
|
||||||
|
ctx.set_ident(&uid, &ident);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ctx.notice(me, from.uid, format!("Vhost for \x02{account}\x02 removed."));
|
ctx.notice(me, from.uid, format!("Vhost for \x02{account}\x02 removed."));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,22 @@ pub fn handle(me: &str, from: &Sender, ctx: &mut ServiceCtx, net: &dyn NetView,
|
||||||
ctx.notice(me, from.uid, "You need to identify to NickServ first.");
|
ctx.notice(me, from.uid, "You need to identify to NickServ first.");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if db.vhost(account).is_none() {
|
let Some(vhost) = db.vhost(account) else {
|
||||||
ctx.notice(me, from.uid, "You have no vhost assigned.");
|
ctx.notice(me, from.uid, "You have no vhost assigned.");
|
||||||
return;
|
return;
|
||||||
}
|
};
|
||||||
match net.host_of(from.uid) {
|
match net.host_of(from.uid) {
|
||||||
Some(host) => {
|
Some(host) => {
|
||||||
let host = host.to_string();
|
let host = host.to_string();
|
||||||
ctx.set_host(from.uid, &host);
|
ctx.set_host(from.uid, &host);
|
||||||
|
// An `ident@host` vhost spoofed the ident too; restore the real one, or
|
||||||
|
// the user keeps the vhost's username for the rest of the session.
|
||||||
|
if vhost.host.contains('@') {
|
||||||
|
if let Some(ident) = net.ident_of(from.uid) {
|
||||||
|
let ident = ident.to_string();
|
||||||
|
ctx.set_ident(from.uid, &ident);
|
||||||
|
}
|
||||||
|
}
|
||||||
ctx.notice(me, from.uid, "Your vhost is off; your normal host is restored.");
|
ctx.notice(me, from.uid, "Your vhost is off; your normal host is restored.");
|
||||||
}
|
}
|
||||||
None => ctx.notice(me, from.uid, "Sorry, that didn't work. Please try again in a moment."),
|
None => ctx.notice(me, from.uid, "Sorry, that didn't work. Please try again in a moment."),
|
||||||
|
|
|
||||||
|
|
@ -249,6 +249,10 @@ impl Network {
|
||||||
self.users.get(uid).map(|u| u.host.as_str())
|
self.users.get(uid).map(|u| u.host.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ident_of(&self, uid: &str) -> Option<&str> {
|
||||||
|
self.users.get(uid).map(|u| u.ident.as_str())
|
||||||
|
}
|
||||||
|
|
||||||
// A user's identity for extban / ban matching (nick, ident, hosts, ip, gecos,
|
// A user's identity for extban / ban matching (nick, ident, hosts, ip, gecos,
|
||||||
// account). `None` if we don't know the uid.
|
// account). `None` if we don't know the uid.
|
||||||
pub fn ban_target<'a>(&'a self, uid: &str) -> Option<echo_api::BanTarget<'a>> {
|
pub fn ban_target<'a>(&'a self, uid: &str) -> Option<echo_api::BanTarget<'a>> {
|
||||||
|
|
@ -577,6 +581,9 @@ impl NetView for Network {
|
||||||
fn host_of(&self, uid: &str) -> Option<&str> {
|
fn host_of(&self, uid: &str) -> Option<&str> {
|
||||||
Network::host_of(self, uid)
|
Network::host_of(self, uid)
|
||||||
}
|
}
|
||||||
|
fn ident_of(&self, uid: &str) -> Option<&str> {
|
||||||
|
Network::ident_of(self, uid)
|
||||||
|
}
|
||||||
fn account_of(&self, uid: &str) -> Option<&str> {
|
fn account_of(&self, uid: &str) -> Option<&str> {
|
||||||
Network::account_of(self, uid)
|
Network::account_of(self, uid)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue