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