@@ -29,9 +29,24 @@ let finally = Xapi_stdext_pervasives.Pervasiveext.finally
2929
3030let krbtgt = " KRBTGT"
3131
32- let ( let * ) = Result. bind
32+ let with_lock = Xapi_stdext_threads.Threadext.Mutex. execute
33+
34+ (* Mutex for serializing AD external auth operations.
35+ * Write ops (enable/disable/set_ldaps) modify winbind config and domain state.
36+ * Read ops (authenticate/query) query AD via wbinfo.
37+ * A plain Mutex serializes both. The [serialize_auth_service] config key
38+ * (default: true) can be set to false to skip locking under concurrent load,
39+ * but only when configure and authenticate calls are never concurrent. *)
40+ let serialize_ext_auth_lock = Mutex. create ()
41+
42+ let cond_sync_ext_auth f =
43+ match ! Xapi_globs. serialize_auth_service with
44+ | true ->
45+ with_lock serialize_ext_auth_lock f
46+ | false ->
47+ f ()
3348
34- let ( let @ ) = ( @@ )
49+ let ( let * ) = Result. bind
3550
3651let ( <!> ) x f = Rresult.R. reword_error f x
3752
@@ -1166,6 +1181,8 @@ end
11661181
11671182(* Enable or disable LDAPS for external authentication *)
11681183let set_ldaps ~__context ~ldaps ~force =
1184+ Context. with_tracing ~__context __FUNCTION__ @@ fun __context ->
1185+ cond_sync_ext_auth @@ fun () ->
11691186 debug " %s:%d set_ldaps ldaps=%b force=%b" __FUNCTION__ __LINE__ ldaps force ;
11701187 let old_domain_info = DomainInfo. of_db ~__context in
11711188
@@ -1410,7 +1427,8 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
14101427 Raises Not_found (* Subject_cannot_be_resolved*) if authentication is not succesful.
14111428 *)
14121429 let get_subject_identifier ~__context subject_name =
1413- let @ __context = Context. with_tracing ~__context __FUNCTION__ in
1430+ Context. with_tracing ~__context __FUNCTION__ @@ fun __context ->
1431+ cond_sync_ext_auth @@ fun () ->
14141432 maybe_raise (get_subject_identifier' ~__context subject_name)
14151433
14161434 (* subject_id Authenticate_username_password(string username, string password)
@@ -1425,7 +1443,8 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
14251443 *)
14261444
14271445 let authenticate_username_password ~__context uname password =
1428- let @ __context = Context. with_tracing ~__context __FUNCTION__ in
1446+ Context. with_tracing ~__context __FUNCTION__ @@ fun __context ->
1447+ cond_sync_ext_auth @@ fun () ->
14291448 (* the `wbinfo --krb5auth` expects the username to be in either SAM or UPN format.
14301449 * we use wbinfo to try to convert the provided [uname] into said format.
14311450 * as a last ditch attempt, we try to auth with the provided [uname]
@@ -1564,7 +1583,8 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
15641583 Raises Not_found (* Subject_cannot_be_resolved*) if subject_id cannot be resolved by external auth service
15651584 *)
15661585 let query_subject_information ~__context (sid : string ) =
1567- let @ __context = Context. with_tracing ~__context __FUNCTION__ in
1586+ Context. with_tracing ~__context __FUNCTION__ @@ fun __context ->
1587+ cond_sync_ext_auth @@ fun () ->
15681588 let res =
15691589 let * name = Wbinfo. name_of_sid sid in
15701590 match name with
@@ -1587,7 +1607,8 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
15871607 supports nested groups (as AD does for example)
15881608 *)
15891609 let query_group_membership ~__context subject_identifier =
1590- let @ __context = Context. with_tracing ~__context __FUNCTION__ in
1610+ Context. with_tracing ~__context __FUNCTION__ @@ fun __context ->
1611+ cond_sync_ext_auth @@ fun () ->
15911612 maybe_raise (Wbinfo. user_domgroups subject_identifier)
15921613
15931614 let assert_join_domain_user_format uname =
@@ -1614,7 +1635,8 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
16141635 does not need long-term.]
16151636 *)
16161637 let on_enable ~__context config_params =
1617- let @ __context = Context. with_tracing ~__context __FUNCTION__ in
1638+ Context. with_tracing ~__context __FUNCTION__ @@ fun __context ->
1639+ cond_sync_ext_auth @@ fun () ->
16181640 let user =
16191641 from_config ~name: " user" ~err_msg: " enable requires user" ~config_params
16201642 in
@@ -1725,7 +1747,8 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
17251747 within the body of the on_disable method)
17261748 *)
17271749 let on_disable ~__context config_params =
1728- let @ __context = Context. with_tracing ~__context __FUNCTION__ in
1750+ Context. with_tracing ~__context __FUNCTION__ @@ fun __context ->
1751+ cond_sync_ext_auth @@ fun () ->
17291752 let user = List. assoc_opt " user" config_params in
17301753 let pass = List. assoc_opt " pass" config_params in
17311754 let {service_name; netbios_name; _} = DomainInfo. of_db ~__context in
@@ -1753,8 +1776,8 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
17531776 starting for the first time after a host boot
17541777 *)
17551778 let on_xapi_initialize ~__context _system_boot =
1756- let @ __context = Context. with_tracing ~__context __FUNCTION__ in
1757-
1779+ Context. with_tracing ~__context __FUNCTION__ @@ fun __context ->
1780+ cond_sync_ext_auth @@ fun () ->
17581781 Winbind. start ~timeout: 5. ~wait_until_success: true ;
17591782 RotateMachinePassword. trigger_rotate ~__context ~start: 5. ;
17601783 Winbind. check_ready_to_serve ~timeout: 300. ;
0 commit comments