pam_ssh_agent/
log.rs

1// Just a quick hack to get logging into syslog. Longer term,
2// this should be done in pam-bindings: https://github.com/anowell/pam-rs/pull/12
3
4use anyhow::{anyhow, Result};
5use std::env;
6use std::fmt::Display;
7use syslog::{Facility, Formatter3164, Logger, LoggerBackend};
8
9pub trait Log {
10    fn debug<S: Display>(&mut self, message: S) -> Result<()>;
11    fn info<S: Display>(&mut self, message: S) -> Result<()>;
12    fn error<S: Display>(&mut self, message: S) -> Result<()>;
13}
14
15pub struct PrintLog;
16
17impl Log for PrintLog {
18    fn debug<S: Display>(&mut self, message: S) -> Result<()> {
19        println!("DEBUG: {}", message);
20        Ok(())
21    }
22
23    fn info<S: Display>(&mut self, message: S) -> Result<()> {
24        println!("INFO: {}", message);
25        Ok(())
26    }
27
28    fn error<S: Display>(&mut self, message: S) -> Result<()> {
29        println!("ERROR: {}", message);
30        Ok(())
31    }
32}
33
34pub struct SyslogLogger {
35    log: Logger<LoggerBackend, Formatter3164>,
36    prefix: String,
37    debug: bool,
38}
39
40impl SyslogLogger {
41    pub(crate) fn new(service_name: &str, debug: bool) -> Self {
42        match syslog::unix(Formatter3164 {
43            facility: Facility::LOG_AUTHPRIV,
44            hostname: None,
45            process: process_name().unwrap_or("unknown".into()),
46            pid: std::process::id(),
47        }) {
48            Ok(log) => SyslogLogger {
49                log,
50                prefix: format!("pam_ssh_agent({}:auth): ", service_name),
51                debug,
52            },
53            Err(e) => panic!("Failed to create syslog: {:?}", e),
54        }
55    }
56}
57
58impl Log for SyslogLogger {
59    fn debug<S: Display>(&mut self, message: S) -> Result<()> {
60        if !self.debug {
61            return Ok(());
62        }
63        self.log
64            .info(format!("{}{}", self.prefix, message))
65            .map_err(|e| anyhow!("failed to log: {:?}", e))
66    }
67
68    fn info<S: Display>(&mut self, message: S) -> Result<()> {
69        self.log
70            .info(format!("{}{}", self.prefix, message))
71            .map_err(|e| anyhow!("failed to log: {:?}", e))
72    }
73
74    fn error<S: Display>(&mut self, message: S) -> Result<()> {
75        self.log
76            .err(format!("{}{}", self.prefix, message))
77            .map_err(|e| anyhow!("failed to log: {:?}", e))
78    }
79}
80
81fn process_name() -> Result<String> {
82    Ok(env::current_exe()?
83        .file_name()
84        .ok_or(anyhow!("no filename"))?
85        .to_string_lossy()
86        .into())
87}