enum AuthState {
None { euid: Euid },
Superuser { euid: Euid, auth: AuthorisationSuperuser },
+ Ssh { id: sshkeys::Id, nonce: sshkeys::Nonce,
+ auth: Authorisation<(sshkeys::Id, sshkeys::Nonce)>, },
}
#[derive(Debug,Clone)]
let preserve_euid = match &cs.authstate {
AuthState::None { euid, .. } => euid,
AuthState::Superuser { euid, .. } => euid,
+ AuthState::Ssh { .. } => throw!(ME::AuthorisationError),
}.clone();
if !enable {
}
Fine
},
+ MC::SetRestrictedSshScope { id, nonce } => {
+ let good_uid = Some(config().ssh_proxy_uid);
+ let auth = cs.authorised_uid(good_uid, Some("SetRestrictedScope"))
+ .map_err(|_| ME::AuthorisationError)?;
+ let auth = auth.therefore_ok();
+ cs.authstate = AuthState::Ssh { id, nonce, auth };
+ Fine
+ },
MC::CreateAccount(AccountDetails {
account, nick, timezone, access, layout
let &client_euid = match &self.authstate {
AuthState::Superuser { euid, .. } => euid,
AuthState::None { euid, .. } => euid,
+ AuthState::Ssh { .. } => throw!(anyhow!(
+ "{}: cannot authorise by uid as ,now in AuthState::Ssh")),
}.as_ref().map_err(|e| e.clone())?;
let server_uid = Uid::current();
if client_euid.is_root() ||
}
#[throws(AuthorisationError)]
-fn do_authorise_scope(cs: &CommandStreamData, _ag: &AccountsGuard,
+fn do_authorise_scope(cs: &CommandStreamData, ag: &AccountsGuard,
wanted: &AccountScope)
-> Authorisation<AccountScope> {
match &cs.authstate {
&AuthState::Superuser { auth, .. } => return auth.into(),
+
+ &AuthState::Ssh { id: sshkey_id, ref nonce, auth } => {
+ let wanted_base_account = AccountName {
+ scope: wanted.clone(),
+ subaccount: default(),
+ };
+ if_chain!{
+ if let Ok::<_,AccountNotFound>
+ ((record, _acctid)) = ag.lookup(&wanted_base_account);
+ if let
+ Some(auth) = record.ssh_keys.check(ag, sshkey_id, &nonce, auth);
+ then { return Ok(auth) }
+ else { throw!(AuthorisationError("ssh key not authorised".into())); }
+ }
+ },
+
_ => {},
}
y.therefore_ok()
}
+ AccountScope::Ssh{..} => {
+ // Should have been dealt with earlier, when we checked authstate.
+ throw!(AuthorisationError(
+ "account must be accessed via ssh proxy"
+ .into()));
+ }
+
AccountScope::Unix { user: wanted } => {
struct InUserList;
pub enum AccountScope {
Server,
Unix { user: String },
+ Ssh { user: String },
}
f(":")?;
f(user)?;
}
+ AS::Ssh { user } => {
+ f("ssh")?;
+ f(":")?;
+ pct(user, &mut f)?;
+ }
};
for n in ns {
f(":")?;
match &self.scope {
AS::Server => "*SERVER*".into(),
AS::Unix { user } => user.clone(),
+ AS::Ssh { user } => user.clone(),
}
}
}
pub enum MgmtCommand {
Noop,
SetSuperuser(bool),
+ SetRestrictedSshScope { id: sshkeys::Id, nonce: sshkeys::Nonce },
CreateAccount(AccountDetails),
UpdateAccount(AccountDetails),
// There is NO WARRANTY.
use crate::prelude::*;
+use pwd::Passwd;
pub const EXIT_SPACE : i32 = 2;
pub const EXIT_NOTFOUND : i32 = 4;
pub specs_dir: Option<String>,
pub sendmail: Option<String>,
pub ssh_proxy_bin: Option<String>,
+ pub ssh_proxy_user: Option<String>,
pub authorized_keys: Option<String>,
pub authorized_keys_include: Option<String>,
pub debug_js_inject_file: Option<String>,
pub specs_dir: String,
pub sendmail: String,
pub ssh_proxy_bin: String,
+ pub ssh_proxy_uid: Uid,
pub authorized_keys: String,
pub authorized_keys_include: String,
pub debug_js_inject: Arc<String>,
template_dir, specs_dir, nwtemplate_dir, wasm_dir, libexec_dir, usvg_bin,
log, bundled_sources, shapelibs, sendmail,
debug_js_inject_file, check_bundled_sources, fake_rng,
- ssh_proxy_bin, authorized_keys, authorized_keys_include,
+ ssh_proxy_bin, ssh_proxy_user, authorized_keys, authorized_keys_include,
} = self;
let game_rng = fake_rng.make_game_rng();
|| format!("{}.static", authorized_keys)
);
+ let ssh_proxy_uid = match ssh_proxy_user {
+ None => Uid::current(),
+ Some(spec) => Uid::from_raw(if let Ok(num) = spec.parse() {
+ num
+ } else {
+ let pwent = (|| Ok::<_,AE>({
+ Passwd::from_name(&spec)
+ .map_err(|e| anyhow!("lookup failed: {}", e))?
+ .ok_or_else(|| anyhow!("does not exist"))?
+ }))()
+ .with_context(|| spec.clone())
+ .context("ssh_proxy_uidr")?;
+ pwent.uid
+ })
+ };
+
let shapelibs = shapelibs.unwrap_or_else(||{
let glob = defpath(None, DEFAULT_LIBRARY_GLOB);
vec![ shapelib::Config1::PathGlob(glob) ]
template_dir, specs_dir, nwtemplate_dir, wasm_dir, libexec_dir,
bundled_sources, shapelibs, sendmail, usvg_bin,
debug_js_inject, check_bundled_sources, game_rng, prctx,
- ssh_proxy_bin, authorized_keys, authorized_keys_include,
+ ssh_proxy_bin, ssh_proxy_uid, authorized_keys, authorized_keys_include,
};
trace_dbg!("config resolved", &server);
Ok(WholeServerConfig {