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 #[allow(clippy::disallowed_methods)]
118 let current_time = OffsetDateTime::now_utc();
120
121 let req_opt = RequestOptions::Main {
122 config_path: DEFAULT_CONFIG_PATH,
123 };
124
125 core::sm_authenticate(pamh, &opts, req_opt, current_time)
126 }
127
128 fn acct_mgmt(pamh: &PamHandle, args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
129 let opts = match ModuleOptions::try_from(&args) {
130 Ok(o) => o,
131 Err(_) => return PamResultCode::PAM_SERVICE_ERR,
132 };
133
134 install_subscriber(opts.debug);
135
136 debug!(?args, ?opts, "acct_mgmt");
137
138 #[allow(clippy::disallowed_methods)]
139 let current_time = OffsetDateTime::now_utc();
141
142 let req_opt = RequestOptions::Main {
143 config_path: DEFAULT_CONFIG_PATH,
144 };
145
146 core::acct_mgmt(pamh, &opts, req_opt, current_time)
147 }
148
149 fn sm_open_session(pamh: &PamHandle, args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
150 let opts = match ModuleOptions::try_from(&args) {
151 Ok(o) => o,
152 Err(_) => return PamResultCode::PAM_SERVICE_ERR,
153 };
154
155 install_subscriber(opts.debug);
156
157 debug!(?args, ?opts, "sm_open_session");
158
159 let req_opt = RequestOptions::Main {
160 config_path: DEFAULT_CONFIG_PATH,
161 };
162
163 core::sm_open_session(pamh, &opts, req_opt)
164 }
165
166 fn sm_close_session(pamh: &PamHandle, args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
167 let opts = match ModuleOptions::try_from(&args) {
168 Ok(o) => o,
169 Err(_) => return PamResultCode::PAM_SERVICE_ERR,
170 };
171
172 install_subscriber(opts.debug);
173
174 debug!(?args, ?opts, "sm_close_session");
175
176 core::sm_close_session(pamh, &opts)
177 }
178
179 fn sm_chauthtok(pamh: &PamHandle, args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
180 let opts = match ModuleOptions::try_from(&args) {
181 Ok(o) => o,
182 Err(_) => return PamResultCode::PAM_SERVICE_ERR,
183 };
184
185 install_subscriber(opts.debug);
186
187 debug!(?args, ?opts, "sm_chauthtok");
188
189 core::sm_chauthtok(pamh, &opts)
190 }
191
192 fn sm_setcred(pamh: &PamHandle, args: Vec<&CStr>, _flags: PamFlag) -> PamResultCode {
193 let opts = match ModuleOptions::try_from(&args) {
194 Ok(o) => o,
195 Err(_) => return PamResultCode::PAM_SERVICE_ERR,
196 };
197
198 install_subscriber(opts.debug);
199
200 debug!(?args, ?opts, "sm_setcred");
201
202 core::sm_setcred(pamh, &opts)
203 }
204}