pam_kanidm/pam/
mod.rs
1pub mod constants;
28pub mod conv;
29pub mod items;
30#[doc(hidden)]
31pub mod macros;
32pub mod module;
33
34use std::collections::BTreeSet;
35use std::convert::TryFrom;
36use std::ffi::CStr;
37
38use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
39use kanidm_unix_common::unix_config::PamNssConfig;
40
41use crate::core::{self, RequestOptions};
42use crate::pam::constants::*;
43use crate::pam::module::{PamHandle, PamHooks};
44use crate::pam_hooks;
45use constants::PamResultCode;
46use time::OffsetDateTime;
47
48use tracing::debug;
49use tracing_subscriber::filter::LevelFilter;
50use tracing_subscriber::fmt;
51use tracing_subscriber::prelude::*;
52
53pub fn get_cfg() -> Result<PamNssConfig, PamResultCode> {
54 PamNssConfig::new()
55 .read_options_from_optional_config(DEFAULT_CONFIG_PATH)
56 .map_err(|_| PamResultCode::PAM_SERVICE_ERR)
57}
58
59fn install_subscriber(debug: bool) {
60 let fmt_layer = fmt::layer().with_target(false);
61
62 let filter_layer = if debug {
63 LevelFilter::DEBUG
64 } else {
65 LevelFilter::ERROR
66 };
67
68 let _ = tracing_subscriber::registry()
69 .with(filter_layer)
70 .with(fmt_layer)
71 .try_init();
72}
73
74#[derive(Debug, Default)]
75pub struct ModuleOptions {
76 pub debug: bool,
77 pub use_first_pass: bool,
78 pub ignore_unknown_user: bool,
79}
80
81impl TryFrom<&Vec<&CStr>> for ModuleOptions {
82 type Error = ();
83
84 fn try_from(args: &Vec<&CStr>) -> Result<Self, Self::Error> {
85 let opts: Result<BTreeSet<&str>, _> = args.iter().map(|cs| cs.to_str()).collect();
86 let gopts = match opts {
87 Ok(o) => o,
88 Err(e) => {
89 println!("Error in module args -> {:?}", e);
90 return Err(());
91 }
92 };
93
94 Ok(ModuleOptions {
95 debug: gopts.contains("debug"),
96 use_first_pass: gopts.contains("use_first_pass"),
97 ignore_unknown_user: gopts.contains("ignore_unknown_user"),
98 })
99 }
100}
101
102pub struct PamKanidm;
103
104pam_hooks!(PamKanidm);
105
106impl PamHooks for PamKanidm {
107 fn sm_authenticate(pamh: &PamHandle, args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
108 let opts = match ModuleOptions::try_from(&args) {
109 Ok(o) => o,
110 Err(_) => return PamResultCode::PAM_SERVICE_ERR,
111 };
112
113 install_subscriber(opts.debug);
114
115 debug!(?args, ?opts, "acct_mgmt");
116
117 let current_time = OffsetDateTime::now_utc();
118
119 let req_opt = RequestOptions::Main {
120 config_path: DEFAULT_CONFIG_PATH,
121 };
122
123 core::sm_authenticate(pamh, &opts, req_opt, current_time)
124 }
125
126 fn acct_mgmt(pamh: &PamHandle, args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
127 let opts = match ModuleOptions::try_from(&args) {
128 Ok(o) => o,
129 Err(_) => return PamResultCode::PAM_SERVICE_ERR,
130 };
131
132 install_subscriber(opts.debug);
133
134 debug!(?args, ?opts, "acct_mgmt");
135
136 let current_time = OffsetDateTime::now_utc();
137
138 let req_opt = RequestOptions::Main {
139 config_path: DEFAULT_CONFIG_PATH,
140 };
141
142 core::acct_mgmt(pamh, &opts, req_opt, current_time)
143 }
144
145 fn sm_open_session(pamh: &PamHandle, args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
146 let opts = match ModuleOptions::try_from(&args) {
147 Ok(o) => o,
148 Err(_) => return PamResultCode::PAM_SERVICE_ERR,
149 };
150
151 install_subscriber(opts.debug);
152
153 debug!(?args, ?opts, "sm_open_session");
154
155 let req_opt = RequestOptions::Main {
156 config_path: DEFAULT_CONFIG_PATH,
157 };
158
159 core::sm_open_session(pamh, &opts, req_opt)
160 }
161
162 fn sm_close_session(pamh: &PamHandle, args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
163 let opts = match ModuleOptions::try_from(&args) {
164 Ok(o) => o,
165 Err(_) => return PamResultCode::PAM_SERVICE_ERR,
166 };
167
168 install_subscriber(opts.debug);
169
170 debug!(?args, ?opts, "sm_close_session");
171
172 core::sm_close_session(pamh, &opts)
173 }
174
175 fn sm_chauthtok(pamh: &PamHandle, args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
176 let opts = match ModuleOptions::try_from(&args) {
177 Ok(o) => o,
178 Err(_) => return PamResultCode::PAM_SERVICE_ERR,
179 };
180
181 install_subscriber(opts.debug);
182
183 debug!(?args, ?opts, "sm_chauthtok");
184
185 core::sm_chauthtok(pamh, &opts)
186 }
187
188 fn sm_setcred(pamh: &PamHandle, args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
189 let opts = match ModuleOptions::try_from(&args) {
190 Ok(o) => o,
191 Err(_) => return PamResultCode::PAM_SERVICE_ERR,
192 };
193
194 install_subscriber(opts.debug);
195
196 debug!(?args, ?opts, "sm_setcred");
197
198 core::sm_setcred(pamh, &opts)
199 }
200}