1use std::convert::TryFrom;
2use std::fs;
3use std::net::IpAddr;
4use std::path::{Path, PathBuf};
5use std::str::FromStr;
6
7use kanidm_proto::internal::{
8 ApiToken, AppLink, CURequest, CUSessionToken, CUStatus, CredentialStatus, IdentifyUserRequest,
9 IdentifyUserResponse, ImageValue, OperationError, RadiusAuthToken, SearchRequest,
10 SearchResponse, UserAuthToken,
11};
12use kanidm_proto::oauth2::OidcWebfingerResponse;
13use kanidm_proto::v1::{
14 AuthIssueSession, AuthRequest, Entry as ProtoEntry, UatStatus, UnixGroupToken, UnixUserToken,
15 WhoamiResponse,
16};
17use kanidmd_lib::idm::identityverification::{
18 IdentifyUserDisplayCodeEvent, IdentifyUserStartEvent, IdentifyUserSubmitCodeEvent,
19};
20use ldap3_proto::simple::*;
21use regex::Regex;
22use tracing::{error, info, instrument, trace};
23use uuid::Uuid;
24
25use compact_jwt::{JweCompact, Jwk, JwsCompact};
26
27use kanidmd_lib::be::BackendTransaction;
28use kanidmd_lib::prelude::*;
29use kanidmd_lib::{
30 event::{OnlineBackupEvent, SearchEvent, SearchResult, WhoamiResult},
31 filter::{Filter, FilterInvalid},
32 idm::account::ListUserAuthTokenEvent,
33 idm::credupdatesession::CredentialUpdateSessionToken,
34 idm::event::{
35 AuthEvent, AuthResult, CredentialStatusEvent, RadiusAuthTokenEvent, UnixGroupTokenEvent,
36 UnixUserAuthEvent, UnixUserTokenEvent,
37 },
38 idm::ldap::{LdapBoundToken, LdapResponseState},
39 idm::oauth2::{
40 AccessTokenIntrospectRequest, AccessTokenIntrospectResponse, AuthorisationRequest,
41 AuthoriseReject, AuthoriseResponse, JwkKeySet, Oauth2Error, Oauth2Rfc8414MetadataResponse,
42 OidcDiscoveryResponse, OidcToken,
43 },
44 idm::server::{DomainInfoRead, IdmServerTransaction},
45 idm::serviceaccount::ListApiTokenEvent,
46 idm::ClientAuthInfo,
47};
48
49use super::QueryServerReadV1;
50
51impl QueryServerReadV1 {
54 #[instrument(
64 level = "info",
65 name = "search",
66 skip_all,
67 fields(uuid = ?eventid)
68 )]
69 pub async fn handle_search(
70 &self,
71 client_auth_info: ClientAuthInfo,
72 req: SearchRequest,
73 eventid: Uuid,
74 ) -> Result<SearchResponse, OperationError> {
75 let ct = duration_from_epoch_now();
77 let mut idms_prox_read = self.idms.proxy_read().await?;
78 let ident = idms_prox_read
79 .validate_client_auth_info_to_ident(client_auth_info, ct)
80 .map_err(|e| {
81 error!(?e, "Invalid identity");
82 e
83 })?;
84
85 let search =
87 SearchEvent::from_message(ident, &req, &mut idms_prox_read.qs_read).map_err(|e| {
88 error!(?e, "Failed to begin search");
89 e
90 })?;
91
92 trace!(?search, "Begin event");
93
94 let entries = idms_prox_read.qs_read.search_ext(&search)?;
95
96 SearchResult::new(&mut idms_prox_read.qs_read, &entries).map(SearchResult::response)
97 }
98
99 #[instrument(
100 level = "info",
101 name = "auth",
102 skip_all,
103 fields(uuid = ?eventid)
104 )]
105 pub async fn handle_auth(
106 &self,
107 sessionid: Option<Uuid>,
108 req: AuthRequest,
109 eventid: Uuid,
110 client_auth_info: ClientAuthInfo,
111 ) -> Result<AuthResult, OperationError> {
112 let ct = duration_from_epoch_now();
117 let mut idm_auth = self.idms.auth().await?;
118 security_info!(?sessionid, ?req, "Begin auth event");
119
120 let ae = AuthEvent::from_message(sessionid, req).map_err(|e| {
124 error!(err = ?e, "Failed to parse AuthEvent");
125 e
126 })?;
127
128 idm_auth.expire_auth_sessions(ct).await;
132
133 let res = idm_auth
136 .auth(&ae, ct, client_auth_info)
137 .await
138 .and_then(|r| idm_auth.commit().map(|_| r));
139
140 security_info!(?res, "Sending auth result");
141
142 res
143 }
144
145 #[instrument(
146 level = "info",
147 name = "reauth",
148 skip_all,
149 fields(uuid = ?eventid)
150 )]
151 pub async fn handle_reauth(
152 &self,
153 client_auth_info: ClientAuthInfo,
154 issue: AuthIssueSession,
155 eventid: Uuid,
156 ) -> Result<AuthResult, OperationError> {
157 let ct = duration_from_epoch_now();
158 let mut idm_auth = self.idms.auth().await?;
159 security_info!("Begin reauth event");
160
161 let ident = idm_auth
162 .validate_client_auth_info_to_ident(client_auth_info.clone(), ct)
163 .map_err(|e| {
164 error!(?e, "Invalid identity");
165 e
166 })?;
167
168 idm_auth.expire_auth_sessions(ct).await;
172
173 let res = idm_auth
176 .reauth_init(ident, issue, ct, client_auth_info)
177 .await
178 .and_then(|r| idm_auth.commit().map(|_| r));
179
180 security_info!(?res, "Sending reauth result");
181
182 res
183 }
184
185 #[instrument(
186 level = "info",
187 name = "online_backup",
188 skip_all,
189 fields(uuid = ?msg.eventid)
190 )]
191 pub async fn handle_online_backup(
192 &self,
193 msg: OnlineBackupEvent,
194 outpath: &Path,
195 versions: usize,
196 ) -> Result<(), OperationError> {
197 trace!(eventid = ?msg.eventid, "Begin online backup event");
198
199 let now = time::OffsetDateTime::now_utc();
200
201 #[allow(clippy::unwrap_used)]
202 let timestamp = now.format(&Rfc3339).unwrap();
203 let dest_file = outpath.join(format!("backup-{timestamp}.json"));
204
205 if dest_file.exists() {
206 error!(
207 "Online backup file {} already exists, will not overwrite it.",
208 dest_file.display()
209 );
210 return Err(OperationError::InvalidState);
211 }
212
213 {
215 let mut idms_prox_read = self.idms.proxy_read().await?;
216 idms_prox_read
217 .qs_read
218 .get_be_txn()
219 .backup(&dest_file)
220 .map(|()| {
221 info!("Online backup created {} successfully", dest_file.display());
222 })
223 .map_err(|e| {
224 error!(
225 "Online backup failed to create {}: {:?}",
226 dest_file.display(),
227 e
228 );
229 OperationError::InvalidState
230 })?;
231 }
232
233 let re = Regex::new(r"^backup-\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,9})?Z\.json$")
235 .map_err(|error| {
236 error!(
237 "Failed to parse regexp for online backup files: {:?}",
238 error
239 );
240 OperationError::InvalidState
241 })?;
242
243 let mut backup_file_list: Vec<PathBuf> = Vec::new();
245 match fs::read_dir(outpath) {
247 Ok(rd) => {
248 for entry in rd {
249 let pb = entry
251 .map_err(|e| {
252 error!(?e, "Pathbuf access");
253 OperationError::InvalidState
254 })?
255 .path();
256
257 if !pb.is_file() {
259 continue;
260 }
261
262 let file_name = pb.file_name().and_then(|f| f.to_str()).ok_or_else(|| {
264 error!("filename is invalid");
265 OperationError::InvalidState
266 })?;
267 if re.is_match(file_name) {
269 backup_file_list.push(pb.clone());
270 }
271 }
272 }
273 Err(e) => {
274 error!(
275 "Online backup cleanup error read dir {}: {}",
276 outpath.display(),
277 e
278 );
279 return Err(OperationError::InvalidState);
280 }
281 }
282
283 backup_file_list.sort();
285
286 if backup_file_list.len() > versions {
292 let x = backup_file_list.len() - versions;
293 info!(
294 "Online backup cleanup found {} versions, should keep {}, will remove {}",
295 backup_file_list.len(),
296 versions,
297 x
298 );
299 backup_file_list.truncate(x);
300
301 for file in backup_file_list {
303 debug!("Online backup cleanup: removing {:?}", &file);
304 match fs::remove_file(&file) {
305 Ok(_) => {}
306 Err(e) => {
307 error!(
308 "Online backup cleanup failed to remove file {:?}: {:?}",
309 file, e
310 )
311 }
312 };
313 }
314 } else {
315 debug!("Online backup cleanup had no files to remove");
316 };
317
318 Ok(())
319 }
320
321 #[instrument(
322 level = "info",
323 name = "whoami",
324 skip_all,
325 fields(uuid = ?eventid)
326 )]
327 pub async fn handle_whoami(
328 &self,
329 client_auth_info: ClientAuthInfo,
330 eventid: Uuid,
331 ) -> Result<WhoamiResponse, OperationError> {
332 let ct = duration_from_epoch_now();
334 let mut idms_prox_read = self.idms.proxy_read().await?;
335 let ident = idms_prox_read
343 .validate_client_auth_info_to_ident(client_auth_info, ct)
344 .map_err(|e| {
345 error!(?e, "Invalid identity");
346 e
347 })?;
348 let srch =
349 SearchEvent::from_whoami_request(ident, &idms_prox_read.qs_read).map_err(|e| {
350 error!(?e, "Failed to begin whoami");
351 e
352 })?;
353
354 trace!(search = ?srch, "Begin event");
355
356 let mut entries = idms_prox_read.qs_read.search_ext(&srch)?;
357
358 match entries.pop() {
359 Some(e) if entries.is_empty() => {
360 WhoamiResult::new(&mut idms_prox_read.qs_read, &e).map(WhoamiResult::response)
361 }
362 Some(_) => Err(OperationError::InvalidState), _ => Err(OperationError::NoMatchingEntries),
364 }
365 }
366
367 pub async fn pre_validate_client_auth_info(
368 &self,
369 client_auth_info: &mut ClientAuthInfo,
370 ) -> Result<(), OperationError> {
371 let ct = duration_from_epoch_now();
372 let mut idms_prox_read = self.idms.proxy_read().await?;
373 idms_prox_read
374 .pre_validate_client_auth_info(client_auth_info, ct)
375 .map_err(|e| {
376 error!(?e, "Invalid identity");
377 e
378 })
379 }
380
381 #[instrument(
382 level = "info",
383 name = "whoami_uat",
384 skip_all,
385 fields(uuid = ?eventid)
386 )]
387 pub async fn handle_whoami_uat(
388 &self,
389 client_auth_info: &ClientAuthInfo,
390 eventid: Uuid,
391 ) -> Result<UserAuthToken, OperationError> {
392 let ct = duration_from_epoch_now();
393 let mut idms_prox_read = self.idms.proxy_read().await?;
394 idms_prox_read
402 .validate_client_auth_info_to_uat(client_auth_info, ct)
403 .map_err(|e| {
404 error!(?e, "Invalid identity");
405 e
406 })
407 }
408
409 #[instrument(level = "debug", skip_all)]
410 pub async fn handle_oauth2_rs_image_get_image(
412 &self,
413 client_auth_info: ClientAuthInfo,
414 rs: Filter<FilterInvalid>,
415 ) -> Result<Option<ImageValue>, OperationError> {
416 let mut idms_prox_read = self.idms.proxy_read().await?;
417 let ct = duration_from_epoch_now();
418
419 let ident = idms_prox_read
420 .validate_client_auth_info_to_ident(client_auth_info, ct)
421 .map_err(|e| {
422 error!(err = ?e, "Invalid identity in handle_oauth2_rs_image_get_image");
423 e
424 })?;
425 let attrs = vec![Attribute::Image.to_string()];
426
427 let search = SearchEvent::from_internal_message(
428 ident,
429 &rs,
430 Some(attrs.as_slice()),
431 &mut idms_prox_read.qs_read,
432 )?;
433
434 let entries = idms_prox_read.qs_read.search(&search)?;
435 Ok(entries
436 .first()
437 .and_then(|entry| entry.get_ava_single_image(Attribute::Image)))
438 }
439
440 #[instrument(
441 level = "info",
442 skip_all,
443 fields(uuid = ?eventid)
444 )]
445 pub async fn handle_internalsearch(
446 &self,
447 client_auth_info: ClientAuthInfo,
448 filter: Filter<FilterInvalid>,
449 attrs: Option<Vec<String>>,
450 eventid: Uuid,
451 ) -> Result<Vec<ProtoEntry>, OperationError> {
452 let ct = duration_from_epoch_now();
453 let mut idms_prox_read = self.idms.proxy_read().await?;
454 let ident = idms_prox_read
455 .validate_client_auth_info_to_ident(client_auth_info, ct)
456 .map_err(|e| {
457 error!("Invalid identity: {:?}", e);
458 e
459 })?;
460 let srch = match SearchEvent::from_internal_message(
462 ident,
463 &filter,
464 attrs.as_deref(),
465 &mut idms_prox_read.qs_read,
466 ) {
467 Ok(s) => s,
468 Err(e) => {
469 error!("Failed to begin internal api search: {:?}", e);
470 return Err(e);
471 }
472 };
473
474 trace!(?srch, "Begin event");
475
476 match idms_prox_read.qs_read.search_ext(&srch) {
477 Ok(entries) => SearchResult::new(&mut idms_prox_read.qs_read, &entries)
478 .map(|ok_sr| ok_sr.into_proto_array()),
479 Err(e) => Err(e),
480 }
481 }
482
483 #[instrument(
484 level = "info",
485 skip_all,
486 fields(uuid = ?eventid)
487 )]
488 pub async fn handle_search_refers(
489 &self,
490 client_auth_info: ClientAuthInfo,
491 filter: Filter<FilterInvalid>,
492 uuid_or_name: String,
493 attrs: Option<Vec<String>>,
494 eventid: Uuid,
495 ) -> Result<Vec<ProtoEntry>, OperationError> {
496 let ct = duration_from_epoch_now();
497 let mut idms_prox_read = self.idms.proxy_read().await?;
498 let ident = idms_prox_read
499 .validate_client_auth_info_to_ident(client_auth_info, ct)
500 .map_err(|e| {
501 error!("Invalid identity: {:?}", e);
502 e
503 })?;
504
505 let target_uuid = idms_prox_read
506 .qs_read
507 .name_to_uuid(uuid_or_name.as_str())
508 .inspect_err(|err| {
509 error!(?err, "Error resolving id to target");
510 })?;
511
512 let filter = Filter::join_parts_and(
514 filter,
515 filter_all!(f_eq(Attribute::Refers, PartialValue::Refer(target_uuid))),
516 );
517
518 let srch = match SearchEvent::from_internal_message(
520 ident,
521 &filter,
522 attrs.as_deref(),
523 &mut idms_prox_read.qs_read,
524 ) {
525 Ok(s) => s,
526 Err(e) => {
527 error!("Failed to begin internal api search: {:?}", e);
528 return Err(e);
529 }
530 };
531
532 trace!(?srch, "Begin event");
533
534 match idms_prox_read.qs_read.search_ext(&srch) {
535 Ok(entries) => SearchResult::new(&mut idms_prox_read.qs_read, &entries)
536 .map(|ok_sr| ok_sr.into_proto_array()),
537 Err(e) => Err(e),
538 }
539 }
540
541 #[instrument(
542 level = "info",
543 skip_all,
544 fields(uuid = ?eventid)
545 )]
546 pub async fn handle_internalsearchrecycled(
547 &self,
548 client_auth_info: ClientAuthInfo,
549 filter: Filter<FilterInvalid>,
550 attrs: Option<Vec<String>>,
551 eventid: Uuid,
552 ) -> Result<Vec<ProtoEntry>, OperationError> {
553 let ct = duration_from_epoch_now();
554 let mut idms_prox_read = self.idms.proxy_read().await?;
555
556 let ident = idms_prox_read
557 .validate_client_auth_info_to_ident(client_auth_info, ct)
558 .map_err(|e| {
559 error!("Invalid identity: {:?}", e);
560 e
561 })?;
562 let srch = match SearchEvent::from_internal_recycle_message(
564 ident,
565 &filter,
566 attrs.as_deref(),
567 &idms_prox_read.qs_read,
568 ) {
569 Ok(s) => s,
570 Err(e) => {
571 error!("Failed to begin recycled search: {:?}", e);
572 return Err(e);
573 }
574 };
575
576 trace!(?srch, "Begin event");
577
578 match idms_prox_read.qs_read.search_ext(&srch) {
579 Ok(entries) => SearchResult::new(&mut idms_prox_read.qs_read, &entries)
580 .map(|ok_sr| ok_sr.into_proto_array()),
581 Err(e) => Err(e),
582 }
583 }
584
585 #[instrument(
586 level = "info",
587 skip_all,
588 fields(uuid = ?eventid)
589 )]
590 pub async fn handle_internalradiusread(
591 &self,
592 client_auth_info: ClientAuthInfo,
593 uuid_or_name: String,
594 eventid: Uuid,
595 ) -> Result<Option<String>, OperationError> {
596 let ct = duration_from_epoch_now();
597 let mut idms_prox_read = self.idms.proxy_read().await?;
598 let ident = idms_prox_read
599 .validate_client_auth_info_to_ident(client_auth_info, ct)
600 .map_err(|e| {
601 error!("Invalid identity: {:?}", e);
602 e
603 })?;
604
605 let target_uuid = idms_prox_read
606 .qs_read
607 .name_to_uuid(uuid_or_name.as_str())
608 .inspect_err(|err| {
609 error!(?err, "Error resolving id to target");
610 })?;
611
612 let srch = match SearchEvent::from_target_uuid_request(
614 ident,
615 target_uuid,
616 &idms_prox_read.qs_read,
617 ) {
618 Ok(s) => s,
619 Err(e) => {
620 error!("Failed to begin radius read: {:?}", e);
621 return Err(e);
622 }
623 };
624
625 trace!(?srch, "Begin event");
626
627 match idms_prox_read.qs_read.search_ext(&srch) {
629 Ok(mut entries) => {
630 let r = entries
631 .pop()
632 .and_then(|entry| {
634 entry
635 .get_ava_single(Attribute::RadiusSecret)
636 .and_then(|v| v.get_secret_str().map(str::to_string))
637 });
638 Ok(r)
639 }
640 Err(e) => Err(e),
641 }
642 }
643
644 #[instrument(
645 level = "info",
646 skip_all,
647 fields(uuid = ?eventid)
648 )]
649 pub async fn handle_internalradiustokenread(
650 &self,
651 client_auth_info: ClientAuthInfo,
652 uuid_or_name: String,
653 eventid: Uuid,
654 ) -> Result<RadiusAuthToken, OperationError> {
655 let ct = duration_from_epoch_now();
656 let mut idms_prox_read = self.idms.proxy_read().await?;
657
658 let ident = idms_prox_read
659 .validate_client_auth_info_to_ident(client_auth_info, ct)
660 .map_err(|e| {
661 error!("Invalid identity: {:?}", e);
662 e
663 })?;
664
665 let target_uuid = idms_prox_read
666 .qs_read
667 .name_to_uuid(uuid_or_name.as_str())
668 .inspect_err(|err| {
669 error!(?err, "Error resolving id to target");
670 })?;
671
672 let rate = match RadiusAuthTokenEvent::from_parts(
674 ident,
676 target_uuid,
677 ) {
678 Ok(s) => s,
679 Err(e) => {
680 error!("Failed to begin radius token read: {:?}", e);
681 return Err(e);
682 }
683 };
684
685 trace!(?rate, "Begin event");
686
687 idms_prox_read.get_radiusauthtoken(&rate, ct)
688 }
689
690 #[instrument(
691 level = "info",
692 skip_all,
693 fields(uuid = ?eventid)
694 )]
695 pub async fn handle_internalunixusertokenread(
696 &self,
697 client_auth_info: ClientAuthInfo,
698 uuid_or_name: String,
699 eventid: Uuid,
700 ) -> Result<UnixUserToken, OperationError> {
701 let ct = duration_from_epoch_now();
702 let mut idms_prox_read = self.idms.proxy_read().await?;
703
704 let ident = idms_prox_read
705 .validate_client_auth_info_to_ident(client_auth_info, ct)
706 .map_err(|e| {
707 error!("Invalid identity: {:?}", e);
708 e
709 })?;
710
711 let target_uuid = idms_prox_read
712 .qs_read
713 .name_to_uuid(uuid_or_name.as_str())
714 .map_err(|e| {
715 let uuid_or_name_val = match uuid_or_name.is_empty() {
718 true => "<empty uuid_or_name>",
719 false => &uuid_or_name,
720 };
721 admin_info!(
722 err = ?e,
723 "Error resolving {} as gidnumber continuing ...",
724 uuid_or_name_val
725 );
726 e
727 })?;
728
729 let rate = match UnixUserTokenEvent::from_parts(ident, target_uuid) {
731 Ok(s) => s,
732 Err(e) => {
733 error!("Failed to begin unix token read: {:?}", e);
734 return Err(e);
735 }
736 };
737
738 trace!(?rate, "Begin event");
739
740 idms_prox_read.get_unixusertoken(&rate, ct)
741 }
742
743 #[instrument(
744 level = "info",
745 skip_all,
746 fields(uuid = ?eventid)
747 )]
748 pub async fn handle_internalunixgrouptokenread(
749 &self,
750 client_auth_info: ClientAuthInfo,
751 uuid_or_name: String,
752 eventid: Uuid,
753 ) -> Result<UnixGroupToken, OperationError> {
754 let ct = duration_from_epoch_now();
755 let mut idms_prox_read = self.idms.proxy_read().await?;
756 let ident = idms_prox_read
757 .validate_client_auth_info_to_ident(client_auth_info, ct)
758 .map_err(|e| {
759 error!("Invalid identity: {:?}", e);
760 e
761 })?;
762
763 let target_uuid = idms_prox_read
764 .qs_read
765 .name_to_uuid(uuid_or_name.as_str())
766 .map_err(|e| {
767 admin_info!(err = ?e, "Error resolving as gidnumber continuing");
768 e
769 })?;
770
771 let rate = match UnixGroupTokenEvent::from_parts(
773 ident,
775 target_uuid,
776 ) {
777 Ok(s) => s,
778 Err(e) => {
779 error!("Failed to begin unix group token read: {:?}", e);
780 return Err(e);
781 }
782 };
783
784 trace!(?rate, "Begin event");
785
786 idms_prox_read.get_unixgrouptoken(&rate)
787 }
788
789 #[instrument(
790 level = "info",
791 skip_all,
792 fields(uuid = ?eventid)
793 )]
794 pub async fn handle_internalsshkeyread(
795 &self,
796 client_auth_info: ClientAuthInfo,
797 uuid_or_name: String,
798 eventid: Uuid,
799 ) -> Result<Vec<String>, OperationError> {
800 let ct = duration_from_epoch_now();
801 let mut idms_prox_read = self.idms.proxy_read().await?;
802 let ident = idms_prox_read
803 .validate_client_auth_info_to_ident(client_auth_info, ct)
804 .map_err(|e| {
805 error!("Invalid identity: {:?}", e);
806 e
807 })?;
808 let target_uuid = idms_prox_read
809 .qs_read
810 .name_to_uuid(uuid_or_name.as_str())
811 .inspect_err(|err| {
812 error!(?err, "Error resolving id to target");
813 })?;
814
815 let srch = match SearchEvent::from_target_uuid_request(
817 ident,
818 target_uuid,
819 &idms_prox_read.qs_read,
820 ) {
821 Ok(s) => s,
822 Err(e) => {
823 error!("Failed to begin ssh key read: {:?}", e);
824 return Err(e);
825 }
826 };
827
828 trace!(?srch, "Begin event");
829
830 match idms_prox_read.qs_read.search_ext(&srch) {
831 Ok(mut entries) => {
832 let r = entries
833 .pop()
834 .and_then(|e| {
836 e.get_ava_iter_sshpubkeys(Attribute::SshPublicKey)
838 .map(|i| i.collect())
839 })
840 .unwrap_or_else(|| {
841 Vec::new()
843 });
844 Ok(r)
845 }
846 Err(e) => Err(e),
847 }
848 }
849
850 #[instrument(
851 level = "info",
852 skip_all,
853 fields(uuid = ?eventid)
854 )]
855 pub async fn handle_internalsshkeytagread(
856 &self,
857 client_auth_info: ClientAuthInfo,
858 uuid_or_name: String,
859 tag: String,
860 eventid: Uuid,
861 ) -> Result<Option<String>, OperationError> {
862 let ct = duration_from_epoch_now();
863 let mut idms_prox_read = self.idms.proxy_read().await?;
864 let ident = idms_prox_read
865 .validate_client_auth_info_to_ident(client_auth_info, ct)
866 .map_err(|e| {
867 error!("Invalid identity: {:?}", e);
868 e
869 })?;
870 let target_uuid = idms_prox_read
871 .qs_read
872 .name_to_uuid(uuid_or_name.as_str())
873 .inspect_err(|err| {
874 admin_info!(?err, "Error resolving id to target");
875 })?;
876
877 let srch = match SearchEvent::from_target_uuid_request(
879 ident,
880 target_uuid,
881 &idms_prox_read.qs_read,
882 ) {
883 Ok(s) => s,
884 Err(e) => {
885 error!("Failed to begin sshkey tag read: {:?}", e);
886 return Err(e);
887 }
888 };
889
890 trace!(?srch, "Begin event");
891
892 match idms_prox_read.qs_read.search_ext(&srch) {
893 Ok(mut entries) => {
894 let r = entries
895 .pop()
896 .map(|e| {
898 e.get_ava_set(Attribute::SshPublicKey).and_then(|vs| {
900 vs.get_ssh_tag(&tag).map(|pk| pk.to_string())
902 })
903 })
904 .unwrap_or_else(|| {
905 None
907 });
908 Ok(r)
909 }
910 Err(e) => Err(e),
911 }
912 }
913
914 #[instrument(
915 level = "info",
916 skip_all,
917 fields(uuid = ?eventid)
918 )]
919 pub async fn handle_service_account_api_token_get(
920 &self,
921 client_auth_info: ClientAuthInfo,
922 uuid_or_name: String,
923 eventid: Uuid,
924 ) -> Result<Vec<ApiToken>, OperationError> {
925 let ct = duration_from_epoch_now();
926 let mut idms_prox_read = self.idms.proxy_read().await?;
927 let ident = idms_prox_read
928 .validate_client_auth_info_to_ident(client_auth_info, ct)
929 .map_err(|e| {
930 error!("Invalid identity: {:?}", e);
931 e
932 })?;
933 let target = idms_prox_read
934 .qs_read
935 .name_to_uuid(uuid_or_name.as_str())
936 .inspect_err(|err| {
937 error!(?err, "Error resolving id to target");
938 })?;
939
940 let lte = ListApiTokenEvent { ident, target };
941
942 idms_prox_read.service_account_list_api_token(<e)
943 }
944
945 #[instrument(
946 level = "info",
947 skip_all,
948 fields(uuid = ?eventid)
949 )]
950 pub async fn handle_account_user_auth_token_get(
951 &self,
952 client_auth_info: ClientAuthInfo,
953 uuid_or_name: String,
954 eventid: Uuid,
955 ) -> Result<Vec<UatStatus>, OperationError> {
956 let ct = duration_from_epoch_now();
957 let mut idms_prox_read = self.idms.proxy_read().await?;
958 let ident = idms_prox_read
959 .validate_client_auth_info_to_ident(client_auth_info, ct)
960 .map_err(|e| {
961 error!("Invalid identity: {:?}", e);
962 e
963 })?;
964 let target = idms_prox_read
965 .qs_read
966 .name_to_uuid(uuid_or_name.as_str())
967 .inspect_err(|err| {
968 error!(?err, "Error resolving id to target");
969 })?;
970
971 let lte = ListUserAuthTokenEvent { ident, target };
972
973 idms_prox_read.account_list_user_auth_tokens(<e)
974 }
975
976 #[instrument(
977 level = "info",
978 skip_all,
979 fields(uuid = ?eventid)
980 )]
981 pub async fn handle_user_identity_verification(
982 &self,
983 client_auth_info: ClientAuthInfo,
984 eventid: Uuid,
985 user_request: IdentifyUserRequest,
986 other_id: String,
987 ) -> Result<IdentifyUserResponse, OperationError> {
988 trace!("{:?}", &user_request);
989 let ct = duration_from_epoch_now();
990 let mut idms_prox_read = self.idms.proxy_read().await?;
991 let ident = idms_prox_read
992 .validate_client_auth_info_to_ident(client_auth_info, ct)
993 .map_err(|e| {
994 error!("Invalid identity: {:?}", e);
995 e
996 })?;
997 let target = idms_prox_read
998 .qs_read
999 .name_to_uuid(&other_id)
1000 .map_err(|e| {
1001 error!("No user found with the provided ID: {:?}", e);
1002 e
1003 })?;
1004 match user_request {
1005 IdentifyUserRequest::Start => idms_prox_read
1006 .handle_identify_user_start(&IdentifyUserStartEvent::new(target, ident)),
1007 IdentifyUserRequest::DisplayCode => idms_prox_read.handle_identify_user_display_code(
1008 &IdentifyUserDisplayCodeEvent::new(target, ident),
1009 ),
1010 IdentifyUserRequest::SubmitCode { other_totp } => idms_prox_read
1011 .handle_identify_user_submit_code(&IdentifyUserSubmitCodeEvent::new(
1012 target, ident, other_totp,
1013 )),
1014 }
1015 }
1016
1017 #[instrument(
1018 level = "info",
1019 skip_all,
1020 fields(uuid = ?eventid)
1021 )]
1022 pub async fn handle_idmaccountunixauth(
1023 &self,
1024 client_auth_info: ClientAuthInfo,
1025 uuid_or_name: String,
1026 cred: String,
1027 eventid: Uuid,
1028 ) -> Result<Option<UnixUserToken>, OperationError> {
1029 let ct = duration_from_epoch_now();
1030 let mut idm_auth = self.idms.auth().await?;
1031 let ident = idm_auth
1033 .validate_client_auth_info_to_ident(client_auth_info, ct)
1034 .map_err(|e| {
1035 error!(err = ?e, "Invalid identity");
1036 e
1037 })?;
1038
1039 let target_uuid = idm_auth
1040 .qs_read
1041 .name_to_uuid(uuid_or_name.as_str())
1042 .map_err(|e| {
1043 admin_info!(err = ?e, "Error resolving as gidnumber continuing");
1044 e
1045 })?;
1046 let uuae = match UnixUserAuthEvent::from_parts(ident, target_uuid, cred) {
1048 Ok(s) => s,
1049 Err(e) => {
1050 error!(err = ?e, "Failed to begin unix auth");
1051 return Err(e);
1052 }
1053 };
1054
1055 security_info!(event = ?uuae, "Begin unix auth event");
1056
1057 let res = idm_auth
1058 .auth_unix(&uuae, ct)
1059 .await
1060 .and_then(|r| idm_auth.commit().map(|_| r));
1061
1062 security_info!(?res, "Sending result");
1063
1064 res
1065 }
1066
1067 #[instrument(
1068 level = "info",
1069 skip_all,
1070 fields(uuid = ?eventid)
1071 )]
1072 pub async fn handle_idmcredentialstatus(
1073 &self,
1074 client_auth_info: ClientAuthInfo,
1075 uuid_or_name: String,
1076 eventid: Uuid,
1077 ) -> Result<CredentialStatus, OperationError> {
1078 let ct = duration_from_epoch_now();
1079 let mut idms_prox_read = self.idms.proxy_read().await?;
1080
1081 let ident = idms_prox_read
1082 .validate_client_auth_info_to_ident(client_auth_info, ct)
1083 .map_err(|e| {
1084 error!(err = ?e, "Invalid identity");
1085 e
1086 })?;
1087 let target_uuid = idms_prox_read
1088 .qs_read
1089 .name_to_uuid(uuid_or_name.as_str())
1090 .map_err(|e| {
1091 error!(err = ?e, "Error resolving id to target");
1092 e
1093 })?;
1094
1095 let cse = match CredentialStatusEvent::from_parts(
1097 ident,
1099 target_uuid,
1100 ) {
1101 Ok(s) => s,
1102 Err(e) => {
1103 error!(err = ?e, "Failed to begin credential status read");
1104 return Err(e);
1105 }
1106 };
1107
1108 trace!(?cse, "Begin event");
1109
1110 idms_prox_read.get_credentialstatus(&cse)
1111 }
1112
1113 #[instrument(
1114 level = "info",
1115 skip_all,
1116 fields(uuid = ?eventid)
1117 )]
1118 pub async fn handle_idmcredentialupdatestatus(
1119 &self,
1120 session_token: CUSessionToken,
1121 eventid: Uuid,
1122 ) -> Result<CUStatus, OperationError> {
1123 let session_token = JweCompact::from_str(&session_token.token)
1124 .map(|token_enc| CredentialUpdateSessionToken { token_enc })
1125 .map_err(|err| {
1126 error!(?err, "malformed token");
1127 OperationError::InvalidRequestState
1128 })?;
1129
1130 let ct = duration_from_epoch_now();
1132 let idms_cred_update = self.idms.cred_update_transaction().await?;
1133
1134 idms_cred_update
1135 .credential_update_status(&session_token, ct)
1136 .map_err(|e| {
1137 error!(
1138 err = ?e,
1139 "Failed to begin credential_update_status",
1140 );
1141 e
1142 })
1143 .map(|sta| sta.into())
1144 }
1145
1146 #[instrument(
1147 level = "info",
1148 skip_all,
1149 fields(uuid = ?eventid)
1150 )]
1151 pub async fn handle_idmcredentialupdate(
1152 &self,
1153 session_token: CUSessionToken,
1154 scr: CURequest,
1155 eventid: Uuid,
1156 ) -> Result<CUStatus, OperationError> {
1157 let session_token = JweCompact::from_str(&session_token.token)
1158 .map(|token_enc| CredentialUpdateSessionToken { token_enc })
1159 .map_err(|err| {
1160 error!(?err, "Invalid Token - Must be a compact JWE");
1161 OperationError::InvalidRequestState
1162 })?;
1163
1164 let ct = duration_from_epoch_now();
1165 let idms_cred_update = self.idms.cred_update_transaction().await?;
1166
1167 debug!(?scr);
1168
1169 match scr {
1170 CURequest::PrimaryRemove => idms_cred_update
1171 .credential_primary_delete(&session_token, ct)
1172 .map_err(|e| {
1173 error!(
1174 err = ?e,
1175 "Failed to begin credential_primary_delete",
1176 );
1177 e
1178 }),
1179 CURequest::Password(pw) => idms_cred_update
1180 .credential_primary_set_password(&session_token, ct, &pw)
1181 .map_err(|e| {
1182 error!(
1183 err = ?e,
1184 "Failed to begin credential_primary_set_password",
1185 );
1186 e
1187 }),
1188 CURequest::CancelMFAReg => idms_cred_update
1189 .credential_update_cancel_mfareg(&session_token, ct)
1190 .map_err(|e| {
1191 error!(
1192 err = ?e,
1193 "Failed to begin credential_update_cancel_mfareg",
1194 );
1195 e
1196 }),
1197 CURequest::TotpGenerate => idms_cred_update
1198 .credential_primary_init_totp(&session_token, ct)
1199 .map_err(|e| {
1200 error!(
1201 err = ?e,
1202 "Failed to begin credential_primary_init_totp",
1203 );
1204 e
1205 }),
1206 CURequest::TotpVerify(totp_chal, label) => idms_cred_update
1207 .credential_primary_check_totp(&session_token, ct, totp_chal, &label)
1208 .map_err(|e| {
1209 error!(
1210 err = ?e,
1211 "Failed to begin credential_primary_check_totp",
1212 );
1213 e
1214 }),
1215 CURequest::TotpAcceptSha1 => idms_cred_update
1216 .credential_primary_accept_sha1_totp(&session_token, ct)
1217 .map_err(|e| {
1218 error!(
1219 err = ?e,
1220 "Failed to begin credential_primary_accept_sha1_totp",
1221 );
1222 e
1223 }),
1224 CURequest::TotpRemove(label) => idms_cred_update
1225 .credential_primary_remove_totp(&session_token, ct, &label)
1226 .map_err(|e| {
1227 error!(
1228 err = ?e,
1229 "Failed to begin credential_primary_remove_totp",
1230 );
1231 e
1232 }),
1233 CURequest::BackupCodeGenerate => idms_cred_update
1234 .credential_primary_init_backup_codes(&session_token, ct)
1235 .map_err(|e| {
1236 error!(
1237 err = ?e,
1238 "Failed to begin credential_primary_init_backup_codes",
1239 );
1240 e
1241 }),
1242 CURequest::BackupCodeRemove => idms_cred_update
1243 .credential_primary_remove_backup_codes(&session_token, ct)
1244 .map_err(|e| {
1245 error!(
1246 err = ?e,
1247 "Failed to begin credential_primary_remove_backup_codes",
1248 );
1249 e
1250 }),
1251 CURequest::PasskeyInit => idms_cred_update
1252 .credential_passkey_init(&session_token, ct)
1253 .map_err(|e| {
1254 error!(
1255 err = ?e,
1256 "Failed to begin credential_passkey_init",
1257 );
1258 e
1259 }),
1260 CURequest::PasskeyFinish(label, rpkc) => idms_cred_update
1261 .credential_passkey_finish(&session_token, ct, label, &rpkc)
1262 .map_err(|e| {
1263 error!(
1264 err = ?e,
1265 "Failed to begin credential_passkey_finish",
1266 );
1267 e
1268 }),
1269 CURequest::PasskeyRemove(uuid) => idms_cred_update
1270 .credential_passkey_remove(&session_token, ct, uuid)
1271 .map_err(|e| {
1272 error!(
1273 err = ?e,
1274 "Failed to begin credential_passkey_remove"
1275 );
1276 e
1277 }),
1278 CURequest::AttestedPasskeyInit => idms_cred_update
1279 .credential_attested_passkey_init(&session_token, ct)
1280 .map_err(|e| {
1281 error!(
1282 err = ?e,
1283 "Failed to begin credential_attested_passkey_init"
1284 );
1285 e
1286 }),
1287 CURequest::AttestedPasskeyFinish(label, rpkc) => idms_cred_update
1288 .credential_attested_passkey_finish(&session_token, ct, label, &rpkc)
1289 .map_err(|e| {
1290 error!(
1291 err = ?e,
1292 "Failed to begin credential_attested_passkey_finish"
1293 );
1294 e
1295 }),
1296 CURequest::AttestedPasskeyRemove(uuid) => idms_cred_update
1297 .credential_attested_passkey_remove(&session_token, ct, uuid)
1298 .map_err(|e| {
1299 error!(
1300 err = ?e,
1301 "Failed to begin credential_attested_passkey_remove"
1302 );
1303 e
1304 }),
1305 CURequest::UnixPasswordRemove => idms_cred_update
1306 .credential_unix_delete(&session_token, ct)
1307 .inspect_err(|err| {
1308 error!(?err, "Failed to begin credential_unix_delete");
1309 }),
1310 CURequest::UnixPassword(pw) => idms_cred_update
1311 .credential_unix_set_password(&session_token, ct, &pw)
1312 .inspect_err(|err| {
1313 error!(?err, "Failed to begin credential_unix_set_password");
1314 }),
1315
1316 CURequest::SshPublicKey(label, pubkey) => idms_cred_update
1317 .credential_sshkey_add(&session_token, ct, label, pubkey)
1318 .inspect_err(|err| {
1319 error!(?err, "Failed to begin credential_sshkey_remove");
1320 }),
1321
1322 CURequest::SshPublicKeyRemove(label) => idms_cred_update
1323 .credential_sshkey_remove(&session_token, ct, &label)
1324 .inspect_err(|err| {
1325 error!(?err, "Failed to begin credential_sshkey_remove");
1326 }),
1327 }
1328 .map(|sta| sta.into())
1329 }
1330
1331 #[instrument(
1332 level = "info",
1333 skip_all,
1334 fields(uuid = ?eventid)
1335 )]
1336 pub async fn handle_oauth2_basic_secret_read(
1337 &self,
1338 client_auth_info: ClientAuthInfo,
1339 filter: Filter<FilterInvalid>,
1340 eventid: Uuid,
1341 ) -> Result<Option<String>, OperationError> {
1342 let ct = duration_from_epoch_now();
1343 let mut idms_prox_read = self.idms.proxy_read().await?;
1344 let ident = idms_prox_read
1345 .validate_client_auth_info_to_ident(client_auth_info, ct)
1346 .map_err(|e| {
1347 error!("Invalid identity: {:?}", e);
1348 e
1349 })?;
1350
1351 let srch = match SearchEvent::from_internal_message(
1353 ident,
1354 &filter,
1355 None,
1356 &mut idms_prox_read.qs_read,
1357 ) {
1358 Ok(s) => s,
1359 Err(e) => {
1360 error!("Failed to begin oauth2 basic secret read: {:?}", e);
1361 return Err(e);
1362 }
1363 };
1364
1365 trace!(?srch, "Begin event");
1366
1367 match idms_prox_read.qs_read.search_ext(&srch) {
1369 Ok(mut entries) => {
1370 let r = entries
1371 .pop()
1372 .and_then(|entry| {
1374 entry
1375 .get_ava_single(Attribute::OAuth2RsBasicSecret)
1376 .and_then(|v| v.get_secret_str().map(str::to_string))
1377 });
1378 Ok(r)
1379 }
1380 Err(e) => Err(e),
1381 }
1382 }
1383
1384 #[instrument(
1385 level = "info",
1386 skip_all,
1387 fields(uuid = ?eventid)
1388 )]
1389 pub async fn handle_oauth2_authorise(
1390 &self,
1391 client_auth_info: ClientAuthInfo,
1392 auth_req: AuthorisationRequest,
1393 eventid: Uuid,
1394 ) -> Result<AuthoriseResponse, Oauth2Error> {
1395 let ct = duration_from_epoch_now();
1396 let mut idms_prox_read = self
1397 .idms
1398 .proxy_read()
1399 .await
1400 .map_err(Oauth2Error::ServerError)?;
1401 let ident = idms_prox_read
1402 .validate_client_auth_info_to_ident(client_auth_info, ct)
1403 .inspect_err(|e| {
1404 error!("Invalid identity: {:?}", e);
1405 })
1406 .ok();
1407
1408 idms_prox_read.check_oauth2_authorisation(ident.as_ref(), &auth_req, ct)
1410 }
1411
1412 #[instrument(
1413 level = "info",
1414 skip_all,
1415 fields(uuid = ?eventid)
1416 )]
1417 pub async fn handle_oauth2_authorise_reject(
1418 &self,
1419 client_auth_info: ClientAuthInfo,
1420 consent_req: String,
1421 eventid: Uuid,
1422 ) -> Result<AuthoriseReject, OperationError> {
1423 let ct = duration_from_epoch_now();
1424 let mut idms_prox_read = self.idms.proxy_read().await?;
1425 let ident = idms_prox_read
1426 .validate_client_auth_info_to_ident(client_auth_info, ct)
1427 .map_err(|e| {
1428 error!("Invalid identity: {:?}", e);
1429 e
1430 })?;
1431
1432 idms_prox_read.check_oauth2_authorise_reject(&ident, &consent_req, ct)
1433 }
1434
1435 #[instrument(
1436 level = "info",
1437 skip_all,
1438 fields(uuid = ?eventid)
1439 )]
1440 pub async fn handle_oauth2_token_introspect(
1441 &self,
1442 client_auth_info: ClientAuthInfo,
1443 intr_req: AccessTokenIntrospectRequest,
1444 eventid: Uuid,
1445 ) -> Result<AccessTokenIntrospectResponse, Oauth2Error> {
1446 let ct = duration_from_epoch_now();
1447 let mut idms_prox_read = self
1448 .idms
1449 .proxy_read()
1450 .await
1451 .map_err(Oauth2Error::ServerError)?;
1452 idms_prox_read.check_oauth2_token_introspect(&client_auth_info, &intr_req, ct)
1454 }
1455
1456 #[instrument(
1457 level = "info",
1458 skip_all,
1459 fields(uuid = ?eventid)
1460 )]
1461 pub async fn handle_oauth2_openid_userinfo(
1462 &self,
1463 client_id: String,
1464 token: &JwsCompact,
1465 eventid: Uuid,
1466 ) -> Result<OidcToken, Oauth2Error> {
1467 let ct = duration_from_epoch_now();
1468 let mut idms_prox_read = self
1469 .idms
1470 .proxy_read()
1471 .await
1472 .map_err(Oauth2Error::ServerError)?;
1473 idms_prox_read.oauth2_openid_userinfo(&client_id, token, ct)
1474 }
1475
1476 #[instrument(
1477 level = "info",
1478 skip_all,
1479 fields(uuid = ?eventid)
1480 )]
1481 pub async fn handle_oauth2_openid_discovery(
1482 &self,
1483 client_id: String,
1484 eventid: Uuid,
1485 ) -> Result<OidcDiscoveryResponse, OperationError> {
1486 let idms_prox_read = self.idms.proxy_read().await?;
1487 idms_prox_read.oauth2_openid_discovery(&client_id)
1488 }
1489
1490 #[instrument(
1491 level = "info",
1492 skip_all,
1493 fields(uuid = ?eventid)
1494 )]
1495 pub async fn handle_oauth2_webfinger_discovery(
1496 &self,
1497 client_id: &str,
1498 resource_id: &str,
1499 eventid: Uuid,
1500 ) -> Result<OidcWebfingerResponse, OperationError> {
1501 let mut idms_prox_read = self.idms.proxy_read().await?;
1502 idms_prox_read.oauth2_openid_webfinger(client_id, resource_id)
1503 }
1504
1505 #[instrument(
1506 level = "info",
1507 skip_all,
1508 fields(uuid = ?eventid)
1509 )]
1510 pub async fn handle_oauth2_rfc8414_metadata(
1511 &self,
1512 client_id: String,
1513 eventid: Uuid,
1514 ) -> Result<Oauth2Rfc8414MetadataResponse, OperationError> {
1515 let idms_prox_read = self.idms.proxy_read().await?;
1516 idms_prox_read.oauth2_rfc8414_metadata(&client_id)
1517 }
1518
1519 #[instrument(
1520 level = "info",
1521 skip_all,
1522 fields(uuid = ?eventid)
1523 )]
1524 pub async fn handle_oauth2_openid_publickey(
1525 &self,
1526 client_id: String,
1527 eventid: Uuid,
1528 ) -> Result<JwkKeySet, OperationError> {
1529 let idms_prox_read = self.idms.proxy_read().await?;
1530 idms_prox_read.oauth2_openid_publickey(&client_id)
1531 }
1532
1533 #[instrument(
1534 level = "info",
1535 skip_all,
1536 fields(uuid = ?eventid)
1537 )]
1538 pub async fn handle_list_applinks(
1539 &self,
1540 client_auth_info: ClientAuthInfo,
1541 eventid: Uuid,
1542 ) -> Result<Vec<AppLink>, OperationError> {
1543 let ct = duration_from_epoch_now();
1544 let mut idms_prox_read = self.idms.proxy_read().await?;
1545 let ident = idms_prox_read
1546 .validate_client_auth_info_to_ident(client_auth_info, ct)
1547 .map_err(|e| {
1548 error!("Invalid identity: {:?}", e);
1549 e
1550 })?;
1551
1552 idms_prox_read.list_applinks(&ident)
1554 }
1555
1556 #[instrument(
1557 level = "info",
1558 skip_all,
1559 fields(uuid = ?eventid)
1560 )]
1561 pub async fn handle_auth_valid(
1562 &self,
1563 client_auth_info: ClientAuthInfo,
1564 eventid: Uuid,
1565 ) -> Result<(), OperationError> {
1566 let ct = duration_from_epoch_now();
1567 let mut idms_prox_read = self.idms.proxy_read().await?;
1568
1569 idms_prox_read
1570 .validate_client_auth_info_to_ident(client_auth_info, ct)
1571 .map(|_| ())
1572 .map_err(|e| {
1573 error!("Invalid identity: {:?}", e);
1574 e
1575 })
1576 }
1577
1578 #[instrument(
1579 level = "info",
1580 skip_all,
1581 fields(uuid = ?eventid)
1582 )]
1583 pub async fn handle_public_jwk_get(
1585 &self,
1586 key_id: String,
1587 eventid: Uuid,
1588 ) -> Result<Jwk, OperationError> {
1589 let mut idms_prox_read = self.idms.proxy_read().await?;
1590
1591 idms_prox_read.jws_public_jwk(key_id.as_str())
1592 }
1593
1594 #[instrument(
1595 level = "info",
1596 skip_all,
1597 fields(uuid = ?eventid)
1598 )]
1599 pub async fn handle_ldaprequest(
1600 &self,
1601 eventid: Uuid,
1602 protomsg: LdapMsg,
1603 uat: Option<LdapBoundToken>,
1604 ip_addr: IpAddr,
1605 ) -> Option<LdapResponseState> {
1606 let res = match ServerOps::try_from(protomsg) {
1607 Ok(server_op) => self
1608 .ldap
1609 .do_op(&self.idms, server_op, uat, ip_addr, eventid)
1610 .await
1611 .unwrap_or_else(|e| {
1612 error!("do_op failed -> {:?}", e);
1613 LdapResponseState::Disconnect(DisconnectionNotice::gen(
1614 LdapResultCode::Other,
1615 format!("Internal Server Error {:?}", &eventid).as_str(),
1616 ))
1617 }),
1618 Err(_) => LdapResponseState::Disconnect(DisconnectionNotice::gen(
1619 LdapResultCode::ProtocolError,
1620 format!("Invalid Request {:?}", &eventid).as_str(),
1621 )),
1622 };
1623 Some(res)
1624 }
1625
1626 pub fn domain_info_read(&self) -> DomainInfoRead {
1627 self.idms.domain_read()
1628 }
1629}