diff --git a/ocaml/tests/test_data/repository_pkg_of_fullname_all b/ocaml/tests/test_data/repository_pkg_of_fullname_all index 021dec04a83..01b8eab12e4 100644 --- a/ocaml/tests/test_data/repository_pkg_of_fullname_all +++ b/ocaml/tests/test_data/repository_pkg_of_fullname_all @@ -253,7 +253,6 @@ intel-igb-5.3.5.20-2.xs8.x86_64 nss-pem-1.0.3-4.el7.x86_64 gssproxy-0.7.0-17.el7.x86_64 nss-sysinit-3.36.0-7.el7_5.x86_64 -pbis-open-8.2.3-1.7.8.xs8.x86_64 mailx-12.5-19.el7.x86_64 system-config-firewall-base-1.2.29-10.el7.noarch libgomp-4.8.5-28.el7_5.1.x86_64 @@ -464,7 +463,6 @@ broadcom-bnxt-en-1.10.0_216.0.119.1-2.xs8.x86_64 tar-1.26-34.el7.x86_64 avago-megaraid-sas-07.713.01.00+rc1-2.xs8.x86_64 nss-softokn-3.36.0-5.el7_5.x86_64 -pbis-open-upgrade-8.2.2-3.xs8.x86_64 nss-tools-3.36.0-7.el7_5.x86_64 forkexecd-1.22.0-7.xs8.x86_64 libunistring-0.9.3-9.el7.x86_64 diff --git a/ocaml/tests/test_extauth_plugin_ADwinbind.ml b/ocaml/tests/test_extauth_plugin_ADwinbind.ml index b5e392c024e..b851c26a59e 100644 --- a/ocaml/tests/test_extauth_plugin_ADwinbind.ml +++ b/ocaml/tests/test_extauth_plugin_ADwinbind.ml @@ -346,12 +346,12 @@ let test_wbinfo_exception_of_stderr = in matrix |> List.map @@ fun (inp, exp) -> ("", `Quick, check inp exp) - let tests = [ ("ADwinbind:extract_ou_config", ExtractOuConfig.tests) ; ("ADwinbind:test_domainify_uname", test_domainify_uname) ; ("ADwinbind:test_parse_wbinfo_uid_info", test_parse_wbinfo_uid_info) ; ("ADwinbind:test_parse_ldap_stdout", test_parse_ldap_stdout) - ; ("ADwinbind:test_wbinfo_exception_of_stderr", test_wbinfo_exception_of_stderr) + ; ( "ADwinbind:test_wbinfo_exception_of_stderr" + , test_wbinfo_exception_of_stderr ) ] diff --git a/ocaml/xapi/extauth.ml b/ocaml/xapi/extauth.ml index bc833e62371..f8711b8be62 100644 --- a/ocaml/xapi/extauth.ml +++ b/ocaml/xapi/extauth.ml @@ -44,7 +44,7 @@ module Ext_auth = struct | "PAM" -> (*pam/nss unix services*) Authx.AuthX.methods - (* the PBIS authentication plugin *) + (* the external authentication plugin *) | "AD" -> (*windows active directory*) Extauth_ad.methods() diff --git a/ocaml/xapi/extauth_plugin_ADwinbind.ml b/ocaml/xapi/extauth_plugin_ADwinbind.ml index a9525d224fd..c8236b76240 100644 --- a/ocaml/xapi/extauth_plugin_ADwinbind.ml +++ b/ocaml/xapi/extauth_plugin_ADwinbind.ml @@ -29,7 +29,7 @@ let ( let* ) = Result.bind let ( ) x f = Rresult.R.reword_error f x -let (>>|) = Rresult.(>>|) +let ( >>| ) = Rresult.( >>| ) let maybe_raise (x : ('a, exn) result) : 'a = match x with Ok x -> x | Error e -> raise e @@ -68,8 +68,7 @@ let ntlm_auth uname passwd : (unit, exn) result = !Xapi_globs.ntlm_auth_cmd args in Ok () - with _ -> - Error (auth_ex uname) + with _ -> Error (auth_ex uname) module Ldap = struct type user = { @@ -180,7 +179,6 @@ module Ldap = struct ; password_expired= logand user_account_control passw_expire_bit <> 0l } - let net_ads (sid : string) : (string, exn) result = try let args = ["ads"; "sid"; "-d"; debug_level; "--machine-pass"; sid] in @@ -204,7 +202,6 @@ module Ldap = struct end module Wbinfo = struct - let exception_of_stderr = let open Auth_signature in let regex = Re.Perl.(compile (re {|.*(WBC_ERR_[A-Z_]*).*|})) in @@ -241,8 +238,8 @@ module Wbinfo = struct let generic_err () = Error (generic_ex "'wbinfo %s' failed" (String.concat " " args)) in + (* we trust wbinfo will not print any sensitive info on failure *) try - (* we trust wbinfo will not print any sensitive info on failure *) let stdout = Helpers.call_script ~log_output:On_failure wb_cmd args in Ok stdout with @@ -297,8 +294,7 @@ module Wbinfo = struct | [|_; name; _|] -> Some (Other name) | _ -> - None - ) + None) in fun sid -> let args = ["--sid-to-name"; sid] in @@ -348,7 +344,7 @@ module Wbinfo = struct | _ -> Error () - let uid_info_of_uid (uid: int) = + let uid_info_of_uid (uid : int) = let args = ["--uid-info"; string_of_int uid] in let* stdout = call_wbinfo args in parse_uid_info stdout fun () -> parsing_ex args @@ -384,10 +380,27 @@ let query_domain_workgroup ~domain ~db_workgroup = let err_msg = Printf.sprintf "Failed to look up domain %s workgroup" domain in + let hd msg = function + | [] -> + error "%s" msg ; + raise (Auth_service_error (E_LOOKUP, msg)) + | h :: _ -> + h + in try + let kdc = + Helpers.call_script ~log_output:On_failure net_cmd + ["lookup"; "kdc"; domain; "-d"; debug_level] + (* Result like 10.71.212.25:88\n10.62.1.25:88\n*) + |> String.split_on_char '\n' + |> hd "lookup kdc return invalid result" + |> String.split_on_char ':' + |> hd "kdc has invalid address" + in + let lines = Helpers.call_script ~log_output:On_failure net_cmd - ["ads"; "lookup"; "-S"; domain; "-d"; debug_level] + ["ads"; "lookup"; "-S"; kdc; "-d"; debug_level] in match Xapi_cmd_result.of_output_opt ~sep:':' ~key ~lines with | Some v -> @@ -484,17 +497,20 @@ let persist_extauth_config ~domain ~user ~ou_conf ~workgroup = |> debug "update external_auth_configuration for host %s") |> Server_helpers.exec_with_new_task "update external_auth_configuration" -let clean_machine_account ~service_name = function +let disable_machine_account ~service_name = function | Some u, Some p -> ( - (* Clean machine account in DC *) + (* Disable machine account in DC *) let env = [|Printf.sprintf "PASSWD=%s" p|] in - let args = ["ads"; "leave"; "-U"; u; "-d"; debug_level] in + let args = + ["ads"; "leave"; "-U"; u; "--keep-account"; "-d"; debug_level] + in try Helpers.call_script ~env net_cmd args |> ignore ; - debug "Succeed to clean the machine account for domain %s" service_name + debug "Succeed to disable the machine account for domain %s" + service_name with _ -> let msg = - Printf.sprintf "Failed to clean the machine account for domain %s" + Printf.sprintf "Failed to disable the machine account for domain %s" service_name in debug "%s" msg ; @@ -614,37 +630,39 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct Raises auth_failure if authentication is not successful *) -let authenticate_username_password uname password = - (* the ntlm_auth binary expects the username to be in either SAM or UPN format. - * we use wbinfo to try to convert the provided [uname] into said format. - * as a last ditch attempt, we try to auth with the provided [uname] - * - * see CA-346287 for more information *) - let orig_uname = uname in - (let* sid = - (* we change the exception, since otherwise we get an (incorrect) error - * message saying that credentials are correct, but we are not authorized *) - get_subject_identifier' uname function - | Auth_failure _ as e -> - e - | Auth_service_error (E_GENERIC, msg) -> - Auth_failure msg - | e -> - D.error "authenticate_username_password:ex: %s" (Printexc.to_string e) ; - Auth_failure - (Printf.sprintf "couldn't get SID from username='%s'" uname) - in - let* () = - match Wbinfo.name_of_sid sid >>| Wbinfo.string_of_name with - | Error e -> - D.warn "authenticate_username_password: trying original uname. ex: %s" - (Printexc.to_string e) ; - ntlm_auth orig_uname password - | Ok uname -> - ntlm_auth orig_uname password - in - Ok sid) - |> maybe_raise + let authenticate_username_password uname password = + (* the ntlm_auth binary expects the username to be in either SAM or UPN format. + * we use wbinfo to try to convert the provided [uname] into said format. + * as a last ditch attempt, we try to auth with the provided [uname] + * + * see CA-346287 for more information *) + let orig_uname = uname in + (let* sid = + (* we change the exception, since otherwise we get an (incorrect) error + * message saying that credentials are correct, but we are not authorized *) + get_subject_identifier' uname function + | Auth_failure _ as e -> + e + | Auth_service_error (E_GENERIC, msg) -> + Auth_failure msg + | e -> + D.error "authenticate_username_password:ex: %s" + (Printexc.to_string e) ; + Auth_failure + (Printf.sprintf "couldn't get SID from username='%s'" uname) + in + let* () = + match Wbinfo.name_of_sid sid >>| Wbinfo.string_of_name with + | Error e -> + D.warn + "authenticate_username_password: trying original uname. ex: %s" + (Printexc.to_string e) ; + ntlm_auth orig_uname password + | Ok uname -> + ntlm_auth orig_uname password + in + Ok sid) + |> maybe_raise (* subject_id Authenticate_ticket(string ticket) @@ -814,7 +832,7 @@ let authenticate_username_password uname password = let user = List.assoc_opt "user" config_params in let pass = List.assoc_opt "pass" config_params in let {service_name; _} = get_domain_info_from_db () in - clean_machine_account ~service_name (user, pass) ; + disable_machine_account ~service_name (user, pass) ; (* Clean local resources *) clean_local_resources () ; (* Clean extauth config *) diff --git a/ocaml/xapi/xapi.ml b/ocaml/xapi/xapi.ml index d5275efd768..a6563fab5cc 100644 --- a/ocaml/xapi/xapi.ml +++ b/ocaml/xapi/xapi.ml @@ -1364,7 +1364,7 @@ let server_init () = , fun () -> call_extauth_hook_script_before_xapi_initialize ~__context ) - ; ( "Initializing lwsmd service" + ; ( "Initializing AD external auth service" , [Startup.NoExnRaising] , fun () -> Extauth_ad.init_service ~__context ) ; ( "Calling on_xapi_initialize event hook in the external \ diff --git a/ocaml/xapi/xapi_host.ml b/ocaml/xapi/xapi_host.ml index 6e6c6efd5bd..dce62e92743 100644 --- a/ocaml/xapi/xapi_host.ml +++ b/ocaml/xapi/xapi_host.ml @@ -1217,7 +1217,7 @@ let set_hostname_live ~__context ~host ~hostname = let current_auth_type = Db.Host.get_external_auth_type ~__context ~self:host in - (* the AD/Likewise extauth plugin is incompatible with a hostname change *) + (* the AD extauth plugin is incompatible with a hostname change *) ( if current_auth_type = Xapi_globs.auth_type_AD then let current_service_name = Db.Host.get_external_auth_service_name ~__context ~self:host