Skip to content

Commit

Permalink
Merge pull request #4 from nresare/use_syslog
Browse files Browse the repository at this point in the history
Use syslog, change error handling
  • Loading branch information
nresare authored Jul 31, 2023
2 parents 550dc6c + 3673221 commit 255e79e
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 18 deletions.
9 changes: 7 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pam-ssh-agent"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
license = "MIT OR Apache-2.0"
repository = "https://github.com/nresare/pam-ssh-agent"
Expand All @@ -13,10 +13,15 @@ name = "pam_ssh_agent"
crate-type = ["lib", "cdylib"]

[dependencies]
ssh-agent-client-rs = "0.4.0"
ssh-agent-client-rs = "0.5.0"
getrandom = "0.2.9"
ssh-key = { version = "0.5.1", features = ["rsa", "dsa", "ed25519", "ecdsa", "p256", "p384"] }
# we need the signature that ssh-key uses
signature = "1.6.4"
anyhow = "1.0.72"
pam-bindings = "0.1.1"
syslog = "6.1.0"

# Since we are building on ubuntu 2022.04, we need to downgrade this
# to a version that supports the compiler
time="=0.3.23"
3 changes: 1 addition & 2 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ Section: libs
Priority: optional
Maintainer: Noa <[email protected]>
Build-Depends: debhelper-compat (= 13),
libpam0g-dev,
cargo
libpam0g-dev
Standards-Version: 4.6.0
Homepage: https://github.com/nresare/pam-ssh-agent
Rules-Requires-Root: no
Expand Down
3 changes: 2 additions & 1 deletion examples/authenticator.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use anyhow::Result;
use pam_ssh_agent::authenticate;
use ssh_agent_client_rs::Client;
use std::env;
use std::path::Path;

fn main() -> Result<(), ssh_agent_client_rs::Error> {
fn main() -> Result<()> {
let path = env::var("SSH_AUTH_SOCK").expect("SSH_AUTH_SOCK is not set");
let client = Client::connect(Path::new(path.as_str()))?;

Expand Down
2 changes: 1 addition & 1 deletion src/auth.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
pub use crate::agent::SSHAgent;
use crate::keys::KeyHolder;
use anyhow::Result;
use getrandom::getrandom;
use signature::Verifier;
use ssh_agent_client_rs::Result;
use ssh_key::PublicKey;
use std::path::Path;

Expand Down
72 changes: 60 additions & 12 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,78 @@ use std::env;
use pam::constants::{PamFlag, PamResultCode};
use pam::module::{PamHandle, PamHooks};

use anyhow::{anyhow, Context, Result};
use ssh_agent_client_rs::Client;
use std::ffi::CStr;
use std::fmt::Display;
use std::path::Path;
use syslog::{Facility, Formatter3164, Logger, LoggerBackend};

struct PamSshAgent;
pam::pam_hooks!(PamSshAgent);

impl PamHooks for PamSshAgent {
fn acct_mgmt(_pamh: &mut PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
PamResultCode::PAM_SUCCESS
fn sm_authenticate(
_pam_handle: &mut PamHandle,
_args: Vec<&CStr>,
_flags: PamFlag,
) -> PamResultCode {
let mut log = SyslogLogger::new();

match do_authenticate(&mut log) {
Ok(_) => PamResultCode::PAM_SUCCESS,
Err(err) => {
for line in format!("{err:?}").split('\n') {
log.error(line).expect("Failed to log");
}
PamResultCode::PAM_AUTH_ERR
}
}
}
}

fn do_authenticate(log: &mut SyslogLogger) -> Result<()> {
let path = env::var("SSH_AUTH_SOCK")
.context("Required environment variable SSH_AUTH_SOCK is not set")?;
log.info(format!("Authenticating using ssh-agent at '{path}'"))?;
let ssh_agent_client = Client::connect(Path::new(path.as_str()))?;
match authenticate("/etc/sudo_ssh_keys", ssh_agent_client)? {
true => Ok(()),
false => Err(anyhow!("Agent did not know of any of the allowed keys")),
}
}

fn sm_authenticate(_pamh: &mut PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
let path = env::var("SSH_AUTH_SOCK").expect("SSH_AUTH_SOCK is not set");
let ssh_agent_client = Client::connect(Path::new(path.as_str())).unwrap();
let result = authenticate("/etc/sudo_ssh_keys", ssh_agent_client).unwrap();
if result {
PamResultCode::PAM_SUCCESS
} else {
PamResultCode::PAM_AUTH_ERR
// Just a quick hack to get logging into syslog. Longer term,
// this should be done pam-bindings: https://github.com/anowell/pam-rs/pull/12

const PREFIX: &str = "pam_ssh_agent(sudo:auth): ";

struct SyslogLogger {
log: Logger<LoggerBackend, Formatter3164>,
}

impl SyslogLogger {
fn new() -> Self {
match syslog::unix(Formatter3164 {
facility: Facility::LOG_AUTHPRIV,
hostname: None,
process: String::from("unknown"),
pid: std::process::id(),
}) {
Ok(log) => SyslogLogger { log },
Err(e) => panic!("Failed to create syslog: {e:?}"),
}
}

fn sm_setcred(_pamh: &mut PamHandle, _args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
PamResultCode::PAM_SUCCESS
fn info<S: Display>(&mut self, message: S) -> Result<()> {
self.log
.info(format!("{PREFIX}{message}"))
.map_err(|e| anyhow!("failed to log: {e:?}"))
}

fn error<S: Display>(&mut self, message: S) -> Result<()> {
self.log
.err(format!("{PREFIX}{message}"))
.map_err(|e| anyhow!("failed to log: {e:?}"))
}
}

0 comments on commit 255e79e

Please sign in to comment.