1use crate::idm::AuthState;
2use crate::prelude::*;
3use compact_jwt::JwsCompact;
4use kanidm_proto::v1::{AuthCredential, AuthIssueSession, AuthMech, AuthRequest, AuthStep};
5
6#[cfg(test)]
7use std::sync::Arc;
8#[cfg(test)]
9use webauthn_rs::prelude::PublicKeyCredential;
10
11#[cfg(test)]
12pub(crate) struct PasswordChangeEvent {
13 pub ident: Identity,
14 pub target: Uuid,
15 pub cleartext: String,
16}
17
18#[cfg(test)]
19impl PasswordChangeEvent {
20 pub fn new_internal(target: Uuid, cleartext: &str) -> Self {
21 PasswordChangeEvent {
22 ident: Identity::from_internal(),
23 target,
24 cleartext: cleartext.to_string(),
25 }
26 }
27}
28
29pub struct UnixPasswordChangeEvent {
30 pub ident: Identity,
31 pub target: Uuid,
32 pub cleartext: String,
33}
34
35impl UnixPasswordChangeEvent {
36 #[cfg(test)]
37 pub fn new_internal(target: Uuid, cleartext: &str) -> Self {
38 UnixPasswordChangeEvent {
39 ident: Identity::from_internal(),
40 target,
41 cleartext: cleartext.to_string(),
42 }
43 }
44
45 pub fn from_parts(
46 ident: Identity,
48 target: Uuid,
49 cleartext: String,
50 ) -> Result<Self, OperationError> {
51 Ok(UnixPasswordChangeEvent {
52 ident,
53 target,
54 cleartext,
55 })
56 }
57}
58
59#[derive(Debug)]
60pub struct GeneratePasswordEvent {
61 pub ident: Identity,
62 pub target: Uuid,
63}
64
65impl GeneratePasswordEvent {
66 pub fn from_parts(
67 ident: Identity,
69 target: Uuid,
70 ) -> Result<Self, OperationError> {
71 Ok(GeneratePasswordEvent { ident, target })
72 }
73}
74
75#[derive(Debug)]
76pub struct RegenerateRadiusSecretEvent {
77 pub ident: Identity,
78 pub target: Uuid,
79}
80
81impl RegenerateRadiusSecretEvent {
82 pub fn from_parts(
83 ident: Identity,
85 target: Uuid,
86 ) -> Result<Self, OperationError> {
87 Ok(RegenerateRadiusSecretEvent { ident, target })
88 }
89
90 #[cfg(test)]
91 pub fn new_internal(target: Uuid) -> Self {
92 let ident = Identity::from_internal();
93
94 RegenerateRadiusSecretEvent { ident, target }
95 }
96}
97
98#[derive(Debug)]
99pub struct RadiusAuthTokenEvent {
100 pub ident: Identity,
101 pub target: Uuid,
102}
103
104impl RadiusAuthTokenEvent {
105 pub fn from_parts(
106 ident: Identity,
108 target: Uuid,
109 ) -> Result<Self, OperationError> {
110 Ok(RadiusAuthTokenEvent { ident, target })
111 }
112
113 #[cfg(test)]
114 pub fn new_impersonate(e: Arc<Entry<EntrySealed, EntryCommitted>>, target: Uuid) -> Self {
115 let ident = Identity::from_impersonate_entry_readonly(e);
116
117 RadiusAuthTokenEvent { ident, target }
118 }
119}
120
121#[derive(Debug)]
122pub struct UnixUserTokenEvent {
123 pub ident: Identity,
124 pub target: Uuid,
125}
126
127impl UnixUserTokenEvent {
128 pub fn from_parts(
129 ident: Identity,
131 target: Uuid,
132 ) -> Result<Self, OperationError> {
133 Ok(UnixUserTokenEvent { ident, target })
134 }
135
136 #[cfg(test)]
137 pub fn new_internal(target: Uuid) -> Self {
138 let ident = Identity::from_internal();
139
140 UnixUserTokenEvent { ident, target }
141 }
142}
143
144#[derive(Debug)]
145pub struct UnixGroupTokenEvent {
146 pub ident: Identity,
147 pub target: Uuid,
148}
149
150impl UnixGroupTokenEvent {
151 pub fn from_parts(
152 ident: Identity,
154 target: Uuid,
155 ) -> Result<Self, OperationError> {
156 Ok(UnixGroupTokenEvent { ident, target })
157 }
158
159 #[cfg(test)]
160 pub fn new_impersonate(e: Arc<Entry<EntrySealed, EntryCommitted>>, target: Uuid) -> Self {
161 let ident = Identity::from_impersonate_entry_readonly(e);
162
163 UnixGroupTokenEvent { ident, target }
164 }
165}
166
167pub struct UnixUserAuthEvent {
168 pub ident: Identity,
169 pub target: Uuid,
170 pub cleartext: String,
171}
172
173impl std::fmt::Debug for UnixUserAuthEvent {
174 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
175 f.debug_struct("UnixUserAuthEvent")
176 .field("ident", &self.ident)
177 .field("target", &self.target)
178 .finish()
179 }
180}
181
182impl UnixUserAuthEvent {
183 #[cfg(test)]
184 pub fn new_internal(target: Uuid, cleartext: &str) -> Self {
185 UnixUserAuthEvent {
186 ident: Identity::from_internal(),
187 target,
188 cleartext: cleartext.to_string(),
189 }
190 }
191
192 pub fn from_parts(
193 ident: Identity,
194 target: Uuid,
195 cleartext: String,
196 ) -> Result<Self, OperationError> {
197 Ok(UnixUserAuthEvent {
198 ident,
199 target,
200 cleartext,
201 })
202 }
203}
204
205#[derive(Debug)]
206pub struct CredentialStatusEvent {
207 pub ident: Identity,
208 pub target: Uuid,
209}
210
211impl CredentialStatusEvent {
212 pub fn from_parts(
213 ident: Identity,
215 target: Uuid,
216 ) -> Result<Self, OperationError> {
217 Ok(CredentialStatusEvent { ident, target })
218 }
219
220 #[cfg(test)]
221 pub fn new_internal(target: Uuid) -> Self {
222 let ident = Identity::from_internal();
223
224 CredentialStatusEvent { ident, target }
225 }
226}
227
228pub struct LdapAuthEvent {
229 pub target: Uuid,
231 pub cleartext: String,
232}
233
234impl LdapAuthEvent {
235 pub fn from_parts(target: Uuid, cleartext: String) -> Result<Self, OperationError> {
236 Ok(LdapAuthEvent {
239 target,
241 cleartext,
242 })
243 }
244}
245
246pub struct LdapTokenAuthEvent {
247 pub token: JwsCompact,
248}
249
250impl LdapTokenAuthEvent {
251 pub fn from_parts(token: JwsCompact) -> Result<Self, OperationError> {
252 Ok(LdapTokenAuthEvent { token })
253 }
254}
255
256pub struct LdapApplicationAuthEvent {
257 pub application: String,
258 pub target: Uuid,
259 pub cleartext: String,
260}
261
262impl LdapApplicationAuthEvent {
263 pub fn new(app_name: &str, usr_uuid: Uuid, cleartext: String) -> Result<Self, OperationError> {
264 Ok(LdapApplicationAuthEvent {
265 application: app_name.to_string(),
266 target: usr_uuid,
267 cleartext,
268 })
269 }
270}
271
272#[derive(Debug)]
273pub struct AuthEventStepInit {
274 pub username: String,
275 pub issue: AuthIssueSession,
276 pub privileged: bool,
277}
278
279#[derive(Debug)]
280pub struct AuthEventStepCred {
281 pub sessionid: Uuid,
282 pub cred: AuthCredential,
283}
284
285#[derive(Debug)]
286pub struct AuthEventStepMech {
287 pub sessionid: Uuid,
288 pub mech: AuthMech,
289}
290
291#[derive(Debug)]
292pub enum AuthEventStep {
293 Init(AuthEventStepInit),
294 Begin(AuthEventStepMech),
295 Cred(AuthEventStepCred),
296}
297
298impl AuthEventStep {
299 fn from_authstep(aus: AuthStep, sid: Option<Uuid>) -> Result<Self, OperationError> {
300 match aus {
301 AuthStep::Init(username) => {
302 if username.trim().is_empty() {
303 Err(OperationError::EmptyRequest)
304 } else {
305 Ok(AuthEventStep::Init(AuthEventStepInit {
306 username,
307 issue: AuthIssueSession::Token,
308 privileged: false,
309 }))
310 }
311 }
312 AuthStep::Init2 {
313 username,
314 issue,
315 privileged,
316 } => {
317 if username.trim().is_empty() {
318 Err(OperationError::EmptyRequest)
319 } else {
320 Ok(AuthEventStep::Init(AuthEventStepInit {
321 username,
322 issue,
323 privileged,
324 }))
325 }
326 }
327
328 AuthStep::Begin(mech) => match sid {
329 Some(sessionid) => Ok(AuthEventStep::Begin(AuthEventStepMech { sessionid, mech })),
330 None => Err(OperationError::InvalidAuthState(
331 "session id not present in cred presented to 'begin' step".to_string(),
332 )),
333 },
334 AuthStep::Cred(cred) => match sid {
335 Some(sessionid) => Ok(AuthEventStep::Cred(AuthEventStepCred { sessionid, cred })),
336 None => Err(OperationError::InvalidAuthState(
337 "session id not present in cred to 'cred' step".to_string(),
338 )),
339 },
340 }
341 }
342
343 #[cfg(test)]
344 pub fn anonymous_init() -> Self {
345 AuthEventStep::Init(AuthEventStepInit {
346 username: "anonymous".to_string(),
347 issue: AuthIssueSession::Token,
348 privileged: false,
349 })
350 }
351
352 #[cfg(test)]
353 pub fn named_init(name: &str) -> Self {
354 AuthEventStep::Init(AuthEventStepInit {
355 username: name.to_string(),
356 issue: AuthIssueSession::Token,
357 privileged: false,
358 })
359 }
360
361 #[cfg(test)]
362 pub fn begin_mech(sessionid: Uuid, mech: AuthMech) -> Self {
363 AuthEventStep::Begin(AuthEventStepMech { sessionid, mech })
364 }
365
366 #[cfg(test)]
367 pub fn cred_step_anonymous(sid: Uuid) -> Self {
368 AuthEventStep::Cred(AuthEventStepCred {
369 sessionid: sid,
370 cred: AuthCredential::Anonymous,
371 })
372 }
373
374 #[cfg(test)]
375 pub fn cred_step_password(sid: Uuid, pw: &str) -> Self {
376 AuthEventStep::Cred(AuthEventStepCred {
377 sessionid: sid,
378 cred: AuthCredential::Password(pw.to_string()),
379 })
380 }
381
382 #[cfg(test)]
383 pub fn cred_step_totp(sid: Uuid, totp: u32) -> Self {
384 AuthEventStep::Cred(AuthEventStepCred {
385 sessionid: sid,
386 cred: AuthCredential::Totp(totp),
387 })
388 }
389
390 #[cfg(test)]
391 pub fn cred_step_backup_code(sid: Uuid, code: &str) -> Self {
392 AuthEventStep::Cred(AuthEventStepCred {
393 sessionid: sid,
394 cred: AuthCredential::BackupCode(code.to_string()),
395 })
396 }
397
398 #[cfg(test)]
399 pub fn cred_step_passkey(sid: Uuid, passkey_response: PublicKeyCredential) -> Self {
400 AuthEventStep::Cred(AuthEventStepCred {
401 sessionid: sid,
402 cred: AuthCredential::Passkey(Box::new(passkey_response)),
403 })
404 }
405}
406
407#[derive(Debug)]
408pub struct AuthEvent {
409 pub ident: Option<Identity>,
410 pub step: AuthEventStep,
411 }
413
414impl AuthEvent {
415 pub fn from_message(sessionid: Option<Uuid>, req: AuthRequest) -> Result<Self, OperationError> {
416 Ok(AuthEvent {
417 ident: None,
418 step: AuthEventStep::from_authstep(req.step, sessionid)?,
419 })
420 }
421
422 #[cfg(test)]
423 pub fn anonymous_init() -> Self {
424 AuthEvent {
425 ident: None,
426 step: AuthEventStep::anonymous_init(),
427 }
428 }
429
430 #[cfg(test)]
431 pub fn named_init(name: &str) -> Self {
432 AuthEvent {
433 ident: None,
434 step: AuthEventStep::named_init(name),
435 }
436 }
437
438 #[cfg(test)]
439 pub fn begin_mech(sessionid: Uuid, mech: AuthMech) -> Self {
440 AuthEvent {
441 ident: None,
442 step: AuthEventStep::begin_mech(sessionid, mech),
443 }
444 }
445
446 #[cfg(test)]
447 pub fn cred_step_anonymous(sid: Uuid) -> Self {
448 AuthEvent {
449 ident: None,
450 step: AuthEventStep::cred_step_anonymous(sid),
451 }
452 }
453
454 #[cfg(test)]
455 pub fn cred_step_password(sid: Uuid, pw: &str) -> Self {
456 AuthEvent {
457 ident: None,
458 step: AuthEventStep::cred_step_password(sid, pw),
459 }
460 }
461
462 #[cfg(test)]
463 pub fn cred_step_totp(sid: Uuid, totp: u32) -> Self {
464 AuthEvent {
465 ident: None,
466 step: AuthEventStep::cred_step_totp(sid, totp),
467 }
468 }
469
470 #[cfg(test)]
471 pub fn cred_step_backup_code(sid: Uuid, code: &str) -> Self {
472 AuthEvent {
473 ident: None,
474 step: AuthEventStep::cred_step_backup_code(sid, code),
475 }
476 }
477
478 #[cfg(test)]
479 pub fn cred_step_passkey(sid: Uuid, passkey_response: PublicKeyCredential) -> Self {
480 AuthEvent {
481 ident: None,
482 step: AuthEventStep::cred_step_passkey(sid, passkey_response),
483 }
484 }
485}
486
487#[derive(Debug)]
489pub struct AuthResult {
490 pub sessionid: Uuid,
491 pub state: AuthState,
492}
493
494