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
228#[derive(Debug)]
229pub struct ReadBackupCodeEvent {
230 pub ident: Identity,
231 pub target: Uuid,
232}
233
234impl ReadBackupCodeEvent {
235 pub fn from_parts(
236 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 target: Uuid,
254 pub cleartext: String,
255}
256
257impl LdapAuthEvent {
258 pub fn from_parts(target: Uuid, cleartext: String) -> Result<Self, OperationError> {
259 Ok(LdapAuthEvent {
262 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 }
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#[derive(Debug)]
512pub struct AuthResult {
513 pub sessionid: Uuid,
514 pub state: AuthState,
515}
516
517