Skip to content

Commit 0d4c780

Browse files
author
Lin Liu
committed
CP-312368: Query subject group information from xapi db
In XSI-2198, user login failed due to wbinfo failed to report subject details. However, this information is available in db To fix the problem, we enhance as follows - First try to find the details in xapi db - If not found, try wbinfo - Raise Error if neither got the details. Note: the wbinfo is required during subject-add where xapi db does not hve the details. Signed-off-by: Lin Liu <lin.liu01@citrix.com>
1 parent ec8e405 commit 0d4c780

1 file changed

Lines changed: 79 additions & 43 deletions

File tree

ocaml/xapi/extauth_plugin_ADwinbind.ml

Lines changed: 79 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ let ( let@ ) = ( @@ )
3434

3535
let ( <!> ) x f = Rresult.R.reword_error f x
3636

37-
let ( >>| ) = Rresult.( >>| )
38-
3937
let min_debug_level = 0
4038

4139
let 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
661631
end
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+
663697
module 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

Comments
 (0)