kanidmd_lib/idm/
event.rs

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        // qs: &QueryServerWriteTransaction,
47        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        // qs: &QueryServerWriteTransaction,
68        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        // qs: &QueryServerWriteTransaction,
84        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        // qs: &QueryServerReadTransaction,
107        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        // qs: &QueryServerReadTransaction,
130        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        // qs: &QueryServerReadTransaction,
153        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        // qs: &QueryServerReadTransaction,
214        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
228#[derive(Debug)]
229pub struct ReadBackupCodeEvent {
230    pub ident: Identity,
231    pub target: Uuid,
232}
233
234impl ReadBackupCodeEvent {
235    pub fn from_parts(
236        // qs: &QueryServerReadTransaction,
237        ident: Identity,
238        target: Uuid,
239    ) -> Result<Self, OperationError> {
240        Ok(ReadBackupCodeEvent { ident, target })
241    }
242
243    #[cfg(test)]
244    pub fn new_internal(target: Uuid) -> Self {
245        let ident = Identity::from_internal();
246
247        ReadBackupCodeEvent { ident, target }
248    }
249}
250
251pub struct LdapAuthEvent {
252    // pub ident: Identity,
253    pub target: Uuid,
254    pub cleartext: String,
255}
256
257impl LdapAuthEvent {
258    pub fn from_parts(target: Uuid, cleartext: String) -> Result<Self, OperationError> {
259        // let e = Event::from_ro_uat(audit, qs, uat)?;
260
261        Ok(LdapAuthEvent {
262            // event: e,
263            target,
264            cleartext,
265        })
266    }
267}
268
269pub struct LdapTokenAuthEvent {
270    pub token: JwsCompact,
271}
272
273impl LdapTokenAuthEvent {
274    pub fn from_parts(token: JwsCompact) -> Result<Self, OperationError> {
275        Ok(LdapTokenAuthEvent { token })
276    }
277}
278
279pub struct LdapApplicationAuthEvent {
280    pub application: String,
281    pub target: Uuid,
282    pub cleartext: String,
283}
284
285impl LdapApplicationAuthEvent {
286    pub fn new(app_name: &str, usr_uuid: Uuid, cleartext: String) -> Result<Self, OperationError> {
287        Ok(LdapApplicationAuthEvent {
288            application: app_name.to_string(),
289            target: usr_uuid,
290            cleartext,
291        })
292    }
293}
294
295#[derive(Debug)]
296pub struct AuthEventStepInit {
297    pub username: String,
298    pub issue: AuthIssueSession,
299    pub privileged: bool,
300}
301
302#[derive(Debug)]
303pub struct AuthEventStepCred {
304    pub sessionid: Uuid,
305    pub cred: AuthCredential,
306}
307
308#[derive(Debug)]
309pub struct AuthEventStepMech {
310    pub sessionid: Uuid,
311    pub mech: AuthMech,
312}
313
314#[derive(Debug)]
315pub enum AuthEventStep {
316    Init(AuthEventStepInit),
317    Begin(AuthEventStepMech),
318    Cred(AuthEventStepCred),
319}
320
321impl AuthEventStep {
322    fn from_authstep(aus: AuthStep, sid: Option<Uuid>) -> Result<Self, OperationError> {
323        match aus {
324            AuthStep::Init(username) => {
325                if username.trim().is_empty() {
326                    Err(OperationError::EmptyRequest)
327                } else {
328                    Ok(AuthEventStep::Init(AuthEventStepInit {
329                        username,
330                        issue: AuthIssueSession::Token,
331                        privileged: false,
332                    }))
333                }
334            }
335            AuthStep::Init2 {
336                username,
337                issue,
338                privileged,
339            } => {
340                if username.trim().is_empty() {
341                    Err(OperationError::EmptyRequest)
342                } else {
343                    Ok(AuthEventStep::Init(AuthEventStepInit {
344                        username,
345                        issue,
346                        privileged,
347                    }))
348                }
349            }
350
351            AuthStep::Begin(mech) => match sid {
352                Some(sessionid) => Ok(AuthEventStep::Begin(AuthEventStepMech { sessionid, mech })),
353                None => Err(OperationError::InvalidAuthState(
354                    "session id not present in cred presented to 'begin' step".to_string(),
355                )),
356            },
357            AuthStep::Cred(cred) => match sid {
358                Some(sessionid) => Ok(AuthEventStep::Cred(AuthEventStepCred { sessionid, cred })),
359                None => Err(OperationError::InvalidAuthState(
360                    "session id not present in cred to 'cred' step".to_string(),
361                )),
362            },
363        }
364    }
365
366    #[cfg(test)]
367    pub fn anonymous_init() -> Self {
368        AuthEventStep::Init(AuthEventStepInit {
369            username: "anonymous".to_string(),
370            issue: AuthIssueSession::Token,
371            privileged: false,
372        })
373    }
374
375    #[cfg(test)]
376    pub fn named_init(name: &str) -> Self {
377        AuthEventStep::Init(AuthEventStepInit {
378            username: name.to_string(),
379            issue: AuthIssueSession::Token,
380            privileged: false,
381        })
382    }
383
384    #[cfg(test)]
385    pub fn begin_mech(sessionid: Uuid, mech: AuthMech) -> Self {
386        AuthEventStep::Begin(AuthEventStepMech { sessionid, mech })
387    }
388
389    #[cfg(test)]
390    pub fn cred_step_anonymous(sid: Uuid) -> Self {
391        AuthEventStep::Cred(AuthEventStepCred {
392            sessionid: sid,
393            cred: AuthCredential::Anonymous,
394        })
395    }
396
397    #[cfg(test)]
398    pub fn cred_step_password(sid: Uuid, pw: &str) -> Self {
399        AuthEventStep::Cred(AuthEventStepCred {
400            sessionid: sid,
401            cred: AuthCredential::Password(pw.to_string()),
402        })
403    }
404
405    #[cfg(test)]
406    pub fn cred_step_totp(sid: Uuid, totp: u32) -> Self {
407        AuthEventStep::Cred(AuthEventStepCred {
408            sessionid: sid,
409            cred: AuthCredential::Totp(totp),
410        })
411    }
412
413    #[cfg(test)]
414    pub fn cred_step_backup_code(sid: Uuid, code: &str) -> Self {
415        AuthEventStep::Cred(AuthEventStepCred {
416            sessionid: sid,
417            cred: AuthCredential::BackupCode(code.to_string()),
418        })
419    }
420
421    #[cfg(test)]
422    pub fn cred_step_passkey(sid: Uuid, passkey_response: PublicKeyCredential) -> Self {
423        AuthEventStep::Cred(AuthEventStepCred {
424            sessionid: sid,
425            cred: AuthCredential::Passkey(Box::new(passkey_response)),
426        })
427    }
428}
429
430#[derive(Debug)]
431pub struct AuthEvent {
432    pub ident: Option<Identity>,
433    pub step: AuthEventStep,
434    // pub sessionid: Option<Uuid>,
435}
436
437impl AuthEvent {
438    pub fn from_message(sessionid: Option<Uuid>, req: AuthRequest) -> Result<Self, OperationError> {
439        Ok(AuthEvent {
440            ident: None,
441            step: AuthEventStep::from_authstep(req.step, sessionid)?,
442        })
443    }
444
445    #[cfg(test)]
446    pub fn anonymous_init() -> Self {
447        AuthEvent {
448            ident: None,
449            step: AuthEventStep::anonymous_init(),
450        }
451    }
452
453    #[cfg(test)]
454    pub fn named_init(name: &str) -> Self {
455        AuthEvent {
456            ident: None,
457            step: AuthEventStep::named_init(name),
458        }
459    }
460
461    #[cfg(test)]
462    pub fn begin_mech(sessionid: Uuid, mech: AuthMech) -> Self {
463        AuthEvent {
464            ident: None,
465            step: AuthEventStep::begin_mech(sessionid, mech),
466        }
467    }
468
469    #[cfg(test)]
470    pub fn cred_step_anonymous(sid: Uuid) -> Self {
471        AuthEvent {
472            ident: None,
473            step: AuthEventStep::cred_step_anonymous(sid),
474        }
475    }
476
477    #[cfg(test)]
478    pub fn cred_step_password(sid: Uuid, pw: &str) -> Self {
479        AuthEvent {
480            ident: None,
481            step: AuthEventStep::cred_step_password(sid, pw),
482        }
483    }
484
485    #[cfg(test)]
486    pub fn cred_step_totp(sid: Uuid, totp: u32) -> Self {
487        AuthEvent {
488            ident: None,
489            step: AuthEventStep::cred_step_totp(sid, totp),
490        }
491    }
492
493    #[cfg(test)]
494    pub fn cred_step_backup_code(sid: Uuid, code: &str) -> Self {
495        AuthEvent {
496            ident: None,
497            step: AuthEventStep::cred_step_backup_code(sid, code),
498        }
499    }
500
501    #[cfg(test)]
502    pub fn cred_step_passkey(sid: Uuid, passkey_response: PublicKeyCredential) -> Self {
503        AuthEvent {
504            ident: None,
505            step: AuthEventStep::cred_step_passkey(sid, passkey_response),
506        }
507    }
508}
509
510// Probably should be a struct with the session id present.
511#[derive(Debug)]
512pub struct AuthResult {
513    pub sessionid: Uuid,
514    pub state: AuthState,
515}
516
517/*
518impl AuthResult {
519    pub fn response(self) -> AuthResponse {
520        AuthResponse {
521            sessionid: self.sessionid,
522            state: self.state,
523        }
524    }
525}
526*/