Apply the IRC namespace guards (forbid, confusable, frozen) to gRPC account writes
This commit is contained in:
parent
660362a34b
commit
18806c5fe7
2 changed files with 31 additions and 0 deletions
|
|
@ -343,6 +343,10 @@ impl Db {
|
||||||
self.confusable_check = on;
|
self.confusable_check = on;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn confusable_check_enabled(&self) -> bool {
|
||||||
|
self.confusable_check
|
||||||
|
}
|
||||||
|
|
||||||
/// The network defence level (5 = normal, 1 = full lockdown).
|
/// The network defence level (5 = normal, 1 = full lockdown).
|
||||||
pub fn defcon(&self) -> u8 {
|
pub fn defcon(&self) -> u8 {
|
||||||
self.defcon
|
self.defcon
|
||||||
|
|
|
||||||
|
|
@ -13,15 +13,42 @@ impl Engine {
|
||||||
if self.db.exists(name) {
|
if self.db.exists(name) {
|
||||||
return Err(AuthorityStatus::AlreadyExists);
|
return Err(AuthorityStatus::AlreadyExists);
|
||||||
}
|
}
|
||||||
|
// A website write must obey the same namespace guards as an IRC REGISTER, or
|
||||||
|
// it becomes a hole around them (a look-alike "аdmin" that impersonates, a
|
||||||
|
// FORBIDden/reserved nick, or a registration created while frozen).
|
||||||
|
if self.db.registrations_frozen() || self.db.readonly() {
|
||||||
|
return Err(AuthorityStatus::Invalid);
|
||||||
|
}
|
||||||
|
self.authority_name_ok(name)?;
|
||||||
if !self.reg_limiter.allow() {
|
if !self.reg_limiter.allow() {
|
||||||
return Err(AuthorityStatus::RateLimited);
|
return Err(AuthorityStatus::RateLimited);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The namespace guards the IRC REGISTER path enforces (FORBID list + look-alike/
|
||||||
|
// confusable check), applied to every authority write so it can't create a name
|
||||||
|
// IRC would have rejected.
|
||||||
|
fn authority_name_ok(&self, name: &str) -> Result<(), AuthorityStatus> {
|
||||||
|
if self.db.is_forbidden(echo_api::ForbidKind::Nick, name).is_some() {
|
||||||
|
return Err(AuthorityStatus::Invalid);
|
||||||
|
}
|
||||||
|
if self.db.confusable_check_enabled() && echo_api::confusable_reason(name).is_some() {
|
||||||
|
return Err(AuthorityStatus::Invalid);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// Provision an account from pre-derived SCRAM verifiers (bulk backfill from
|
// Provision an account from pre-derived SCRAM verifiers (bulk backfill from
|
||||||
// the authority). No email confirmation — the authority already vouches for it.
|
// the authority). No email confirmation — the authority already vouches for it.
|
||||||
pub fn authority_provision(&mut self, name: &str, scram256: &str, scram512: &str, email: Option<String>) -> AuthorityStatus {
|
pub fn authority_provision(&mut self, name: &str, scram256: &str, scram512: &str, email: Option<String>) -> AuthorityStatus {
|
||||||
|
// Backfill still can't mint a forbidden/look-alike name (skip only the
|
||||||
|
// frozen/rate-limit gates, which don't apply to an authority backfill).
|
||||||
|
if !self.db.exists(name) {
|
||||||
|
if let Err(status) = self.authority_name_ok(name) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
match self.db.provision_account(name, scram256, scram512, email) {
|
match self.db.provision_account(name, scram256, scram512, email) {
|
||||||
Ok(()) => AuthorityStatus::Ok,
|
Ok(()) => AuthorityStatus::Ok,
|
||||||
Err(RegError::Exists) => AuthorityStatus::AlreadyExists,
|
Err(RegError::Exists) => AuthorityStatus::AlreadyExists,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue