@@ -34,8 +34,6 @@ let ( let@ ) = ( @@ )
3434
3535let ( <!> ) x f = Rresult.R. reword_error f x
3636
37- let ( >> | ) = Rresult. ( >> | )
38-
3937let min_debug_level = 0
4038
4139let max_debug_level = 10
@@ -564,37 +562,9 @@ module Wbinfo = struct
564562 let * stdout = call_wbinfo args in
565563 Ok (String. trim stdout)
566564
567- type name = User of string | Other of string
568-
569- let string_of_name = function User x -> x | Other x -> x
570-
571- let name_of_sid =
572- (* example:
573- * $ wbinfo -s S-1-5-21-3143668282-2591278241-912959342-502
574- CONNAPP\krbtgt 1 *)
575- (* the number returned after the name is the 'SID type' (grep for wbcSidType
576- * in samba source code). for our purposes, it is sufficient to assume that
577- * everything that is not a user is some 'other' type*)
578- let regex = Re.Perl. (compile (re {|^ ([^ \s].* )\ (\d+ )\s*$| })) in
579- let get_regex_match x =
580- Option. bind (Re. exec_opt regex x) (fun g ->
581- match Re.Group. all g with
582- | [|_; name; " 1" |] ->
583- Some (User name)
584- | [|_; name; _|] ->
585- Some (Other name)
586- | _ ->
587- None
588- )
589- in
590- fun sid ->
591- let args = [" --sid-to-name" ; sid] in
592- let * stdout = call_wbinfo args in
593- match get_regex_match stdout with
594- | None ->
595- Error (parsing_ex args)
596- | Some x ->
597- Ok x
565+ let sid_to_name sid =
566+ let args = [" --sid-to-name" ; sid] in
567+ call_wbinfo args
598568
599569 let gid_of_sid sid =
600570 let args = [" --sid-to-gid" ; sid] in
@@ -660,6 +630,70 @@ module Wbinfo = struct
660630 parse_uid_info stdout < ! > fun () -> parsing_ex args
661631end
662632
633+ module Subject = struct
634+ type t = User of string | Group of string
635+
636+ let string_of_subject = function User x -> x | Group x -> x
637+
638+ let from_wbinfo =
639+ (* example:
640+ * $ wbinfo -s S-1-5-21-3143668282-2591278241-912959342-502
641+ CONNAPP\krbtgt 1 *)
642+ (* the number returned after the name is the 'SID type' (grep for wbcSidType
643+ * in samba source code). for our purposes, it is sufficient to assume that
644+ * everything that is not a user is some 'other' type*)
645+ let regex = Re.Perl. (compile (re {|^ ([^ \s].* )\s+ (\d+ )\s*$| })) in
646+ let parse_name input sid =
647+ match Re. exec_opt regex input with
648+ | Some g -> (
649+ match Re.Group. all g with
650+ | [|_; name; " 1" |] ->
651+ Ok (User name)
652+ | [|_; name; _|] ->
653+ Ok (Group name)
654+ | _ ->
655+ Error (generic_ex " Failed to parse output '%s' for sid %s" input sid)
656+ )
657+ | None ->
658+ Error (generic_ex " Failed to parse output '%s' for sid %s" input sid)
659+ in
660+ fun sid ->
661+ let * stdout = Wbinfo. sid_to_name sid in
662+ parse_name stdout sid
663+
664+ let from_db ~__context sid =
665+ let open Xapi_database.Db_filter_types in
666+ match
667+ Db.Subject. get_records_where ~__context
668+ ~expr: (Eq (Field " subject_identifier" , Literal sid))
669+ with
670+ | (_ , r ) :: _ ->
671+ let other_config = r.API. subject_other_config in
672+ let * name =
673+ List. assoc_opt " subject-name" other_config
674+ |> Option. to_result
675+ ~none: (generic_ex " subject-name not found in db for sid %s" sid)
676+ in
677+
678+ List. assoc_opt " subject-is-group" other_config
679+ |> Option. map (fun s ->
680+ match String. lowercase_ascii s with
681+ | "true" ->
682+ Group name
683+ | _ ->
684+ User name
685+ )
686+ |> Option. to_result
687+ ~none: (generic_ex " subject-is-group not found in db for sid %s" sid)
688+ | [] ->
689+ Error (generic_ex " Subject not found in db for sid %s" sid)
690+
691+ let ( ||| ) a b = match a with Ok _ -> a | Error _ -> b
692+
693+ let of_sid ~__context sid =
694+ from_db ~__context sid ||| from_wbinfo sid |> maybe_raise
695+ end
696+
663697module Migrate_from_pbis = struct
664698 (* upgrade-pbis-to-winbind handles most of the migration from PBIS database
665699 * to winbind database
@@ -1345,14 +1379,14 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
13451379 (Printf. sprintf " couldn't get SID from username='%s'" uname)
13461380 in
13471381 let * () =
1348- match Wbinfo. name_of_sid sid >> | Wbinfo. string_of_name with
1349- | Error e ->
1382+ match Subject. of_sid ~__context sid |> Subject. string_of_subject with
1383+ | uname ->
1384+ Wbinfo. kerberos_auth uname password
1385+ | exception e ->
13501386 D. warn
13511387 " authenticate_username_password: trying original uname. ex: %s"
13521388 (Printexc. to_string e) ;
13531389 Wbinfo. kerberos_auth orig_uname password
1354- | Ok uname ->
1355- Wbinfo. kerberos_auth uname password
13561390 in
13571391 Ok sid
13581392 )
@@ -1460,17 +1494,19 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
14601494 it's a string*string list anyway for possible future expansion.
14611495 Raises Not_found (* Subject_cannot_be_resolved*) if subject_id cannot be resolved by external auth service
14621496 *)
1497+ (* Fallback uid/gid when the winbind daemon fails to resolve the SID *)
1498+ let invalid_id = - 1
1499+
14631500 let query_subject_information ~__context (sid : string ) =
14641501 let @ __context = Context. with_tracing ~__context __FUNCTION__ in
14651502 let res =
1466- let * name = Wbinfo. name_of_sid sid in
1467- match name with
1468- | User _ ->
1469- let * uid = Wbinfo. uid_of_sid sid in
1503+ match Subject. of_sid ~__context sid with
1504+ | Subject. User _ ->
1505+ let uid = Wbinfo. uid_of_sid sid |> Result. value ~default: invalid_id in
14701506 query_subject_information_user uid sid
1471- | Other name ->
1507+ | Subject. Group name ->
14721508 (* if the name doesn't correspond to a user then it ought to be a group *)
1473- let * gid = Wbinfo. gid_of_sid sid in
1509+ let gid = Wbinfo. gid_of_sid sid |> Result. value ~default: invalid_id in
14741510 Ok (query_subject_information_group name gid sid)
14751511 in
14761512 (* we must raise Not_found here. see xapi_pool.ml:revalidate_subjects *)
0 commit comments