
    g                    R   S SK r S SKrS SKJr  S SKrS SKJrJr  S SKJrJ	r	J
r
  S SKJr  S SKJr  S SKJrJr  S SKJrJrJrJr  S S	KJrJrJrJr  S S
KJrJrJr  S SKJr  S SK J!r!  S SK"J#r#  S SK$J%r%  S SKJ&r&J'r'  S SKJ(r(  S SK)J*r*J+r+J,r,  S SK$J-r-  S SK.J/r/  S r0S r1 " S S\25      r3g)    N)
cmp_to_key)unix2nttimenttime2unix)ldbdsdb	drs_utils)system_session)SamDB)drsuapimisc)Site	Partition	TransportSiteLink)	NCReplicaNCType
nctype_lut	GraphNode)
RepsFromToKCCErrorKCCFailedObject)convert_schedule_to_repltimes)ndr_pack)verify_and_dot)ldif_import_export)setup_graphget_spanning_tree_edges)Vertex)DEBUGDEBUG_FNlogger)debug)cmpc                    U R                  5       (       a  UR                  5       (       d  gU R                  5       (       d  UR                  5       (       a  g[        [        U R                  5      [        UR                  5      5      $ )zHelper to sort DSAs by guid global catalog status

GC DSAs come before non-GC DSAs, other than that, the guids are
sorted in NDR form.

:param dsa1: A DSA object
:param dsa2: Another DSA
:return: -1, 0, or 1, indicating sort order.
   )is_gcr#   r   dsa_guid)dsa1dsa2s     4/usr/lib/python3/dist-packages/samba/kcc/__init__.pysort_dsa_by_gc_and_guidr,   2   sS     zz||DJJLL::<<DJJLLx&(?@@    c                      g)zCan the KCC use SMTP replication?

Currently always returns false because Samba doesn't implement
SMTP transfer for NC changes between DCs.

:return: Boolean (always False)
F r/   r-   r+   is_smtp_replication_availabler0   C   s     r-   c                   6   \ rS rSrSr  S-S jrS rS rS rS r	S	 r
S
 rS rS.S jrS rS rS rS rS rS rS rS rS rS rS.S jrS.S jrS rS rS rS rS rS rS r S  r!S! r"S/S" jr#S# r$S$ r%S% r&S& r'S0S' jr(S1S( jr)   S2S) jr*S.S* jr+S+ r,S,r-g)3KCCN   a  The Knowledge Consistency Checker class.

A container for objects and methods allowing a run of the KCC.  Produces a
set of connections in the samdb for which the Distributed Replication
Service can then utilize to replicate naming contexts

:param unix_now: The putative current time in seconds since 1970.
:param readonly: Don't write to the database.
:param verify: Check topological invariants for the generated graphs
:param debug: Write verbosely to stderr.
:param dot_file_dir: write diagnostic Graphviz files in this directory
Nc                    0 U l         0 U l        SU l        0 U l        0 U l        0 U l        U R
                  R                  U l        U R                  R                  U l        0 U l	        [        5       U l        [        5       U l        SU l        SU l        SU l        SU l        SU l        Xl        ['        U5      U l        X l        X0l        X@l        XPl        g)zmInitializes the partitions class which can hold
our local DCs partitions or all the partitions in
the forest
N)
part_table
site_tableip_transportsitelink_tabledsa_by_dnstrdsa_by_guidgetget_dsa_by_guidstrget_dsakcc_failed_linkssetkcc_failed_connectionskept_connectionsmy_dsa_dnstrmy_dsamy_site_dnstrmy_sitesamdbunix_nowr   nt_nowreadonlyverifyr"   dot_file_dir)selfrG   rI   rJ   r"   rK   s         r+   __init__KCC.__init__[   s       "&"2"2"6"6((,,
 !#&)e#
 !$ !
 !(+ 
(r-   c                     U R                   R                  SU R                   R                  5       -  [        R                  SS9nU H  n[        UR                  5      n[        U5      nUR                  U R                   5        UR                  S:X  a  Xpl        MV  UR                  S:X  a  [        R                  " S5        M~  [        R                   " S	UR                  < S
35        M     U R                  c  [        S5      eg! [        R
                   a!  nUR                  u  p4[        SU-  5      eSnAff = f)zmLoads the inter-site transport objects for Sites

:return: None
:raise KCCError: if no IP transport is found
$CN=Inter-Site Transports,CN=Sites,%sz (objectClass=interSiteTransport)scope
expressionz+Unable to find inter-site transports - (%s)NIPSMTPz2Samba KCC is ignoring the obsolete SMTP transport.z0Samba KCC does not support the transport called .z(there doesn't seem to be an IP transport)rF   searchget_config_basednr   SCOPE_SUBTREELdbErrorargsr   strdnr   load_transportnamer7   r!   r"   warning)rL   rese2enumestrmsgdnstr	transports           r+   load_ip_transportKCC.load_ip_transport   s   	!**##$J$(JJ$@$@$B%C*-*;*;/Q $ SC CKE!%(I$$TZZ0~~%$-!6) / 0 /8~~ @ A   $EFF %+ || 	!77LTH  ! !	!s   AD D=D88D=c                     U R                   R                  SU R                   R                  5       -  [        R                  SS9nU H]  n[        UR                  5      nX`R                  ;   a  M)  [        U5      nUR                  U R                   5        XpR                  U'   M_     g! [        R
                   a!  nUR                  u  p4[        SU-  5      eSnAff = f)zaLoads the inter-site siteLink objects

:return: None
:raise KCCError: if site-links aren't found
rP   z(objectClass=siteLink)rQ   z*Unable to find inter-site siteLinks - (%s)N)rF   rW   rX   r   rY   rZ   r[   r   r\   r]   r8   r   load_sitelink)rL   ra   e3rc   rd   re   rf   sitelinks           r+   load_all_sitelinksKCC.load_all_sitelinks   s    	P**##$J$(JJ$@$@$B%C*-*;*;/G $ IC CKE +++H""4::. *2& 	 || 	P77LTG$NOO	P   AB* *C>CCc                    [        XR                  5      nUR                  U R                  5        [	        UR
                  5      nX0R                  ;  am  X R                  U'   U R                  R                  UR                  5        U R                  R                  S UR                  R                  5        5       5        U R                  U   $ )zHelper for load_my_site and load_all_sites.

Put all the site's DSAs into the KCC indices.

:param dn_str: a site dn_str
:return: the Site object pertaining to the dn_str
c              3   P   #    U  H  n[        UR                  5      U4v   M     g 7fNr\   r(   .0xs     r+   	<genexpr> KCC.load_site.<locals>.<genexpr>   s%      $F-D &)_a$8-Ds   $&)r   rG   	load_siterF   r\   	site_guidr6   r9   update	dsa_tabler:   values)rL   dn_strsiteguids       r+   rz   KCC.load_site   s     FMM*tzz"
 4>>"&$(OOD!$$T^^4## $F-1^^-B-B-D$F F t$$r-   c                     SU R                   R                  5       < SU R                   R                  5       < 3U l        U R	                  U R                  5      U l        g)z7Load the Site object for the local DSA.

:return: None
zCN=z
,CN=Sites,N)rF   server_site_namerX   rD   rz   rE   rL   s    r+   load_my_siteKCC.load_my_site   sF     JJ'')JJ((*, ~~d&8&89r-   c                 \    U R                   R                  SU R                   R                  5       -  [        R                  SS9nU H)  n[        UR                  5      nU R                  U5        M+     g! [        R
                   a!  nUR                  u  p4[        SU-  5      eSnAff = f)zdDiscover all sites and create Site objects.

:return: None
:raise: KCCError if sites can't be found
zCN=Sites,%sz(objectClass=site)rQ   zUnable to find sites - (%s)N)rF   rW   rX   r   rY   rZ   r[   r   r\   r]   rz   )rL   ra   e4rc   rd   re   sitestrs          r+   load_all_sitesKCC.load_all_sites   s    	A**##M$(JJ$@$@$B%C*-*;*;/C $ EC C#&&kGNN7# 	 || 	A77LT84?@@	As   AA6 6B+
B&&B+c           
         SU R                   R                  5       -  n[        R                  " U R                   U5      n U R                   R	                  U[        R
                  S/S9n[        U5      S:w  a  [        SUR                  5       -  5      e[        R                  " U R                   R                  5       5      n	[        R                  " US
   S   S
   5      U	:w  a  [        S5      e[        US
   R                   5      U l        U R$                  R'                  U R"                  5      U l        U R"                  U R*                  ;  a}  [,        R.                  " SU R"                  -  5        U R(                  U R*                  U R"                  '   U R(                  U R0                  [        U R(                  R2                  5      '   gg! [        R                   a  nUR                  u  pV[        SU< SU< SU< S35         U R                   R	                  S[        R
                  S	/S9n[        R                  " U R                   US
   S	   S
   R                  S5      5      nU R                   R	                  U[        R
                  S/S9n SnAGN4! [        R                   a!  nUR                  u  pV[        SU-  5      eSnAff = fSnAff = f)zdDiscover my nTDSDSA dn thru the rootDSE entry

:return: None
:raise: KCCError if DSA can't be found
z	<GUID=%s>
objectGUID)baserR   attrszSearch for dn 'z' [from z
] failed: zL. This typically happens in --importldif mode due to lack of module support. dsServiceNamer   utf8z Unable to find my nTDSDSA - (%s)Nr&   zUnable to find my nTDSDSA at %sz>Did not find the GUID we expected, perhaps due to --importldifzmy_dsa %s isn't in self.dsas_by_dnstr: it must be RODC.
Let's add it, because my_dsa is special!
(likewise for self.dsa_by_guid))rF   get_ntds_GUIDr   DnrW   
SCOPE_BASErZ   r[   r    decoder   lenextended_strr   GUIDr\   r]   rB   rE   r=   rC   r9   r"   DEBUG_DARK_YELLOWr:   r(   )
rL   dn_queryr]   ra   e5rc   rd   service_name_rese	ntds_guids
             r+   load_my_dsaKCC.load_my_dsa   s|    !9!9!;;VVDJJ)	J**##3>>+7. $ :C4 s8q=<??,- . . IIdjj6689	99SVL)!,-: : ; ;  A		Nll**4+<+<=D$5$55## %H %)$5$5	%6 7 48;;Dd//0:>++DS!5!567 6K || 	J77LT574I JJ $(::#4#4";>>><K;L $5 $N  VVDJJ,Q/@CJJ6RT jj''Rs~~/;n ( ><< J vvADHIIJ)	Js7    *G K$&KBJK2KKKKc                     U R                   R                  SU R                   R                  5       -  [        R                  SS9nU H]  n[        UR                  5      nX`R                  ;   a  M)  [        U5      nUR                  U R                   5        XpR                  U'   M_     g! [        R
                   a!  nUR                  u  p4[        SU-  5      eSnAff = f)zDiscover and load all partitions.

Each NC is inserted into the part_table by partition
dn string (not the nCName dn string)

:return: None
:raise: KCCError if partitions can't be found
zCN=Partitions,%sz(objectClass=crossRef)rQ   z Unable to find partitions - (%s)N)rF   rW   rX   r   rY   rZ   r[   r   r\   r]   r5   r   load_partition)rL   ra   e6rc   rd   re   partstrparts           r+   load_all_partitionsKCC.load_all_partitions5  s    	F**##$6$(JJ$@$@$B%C*-*;*;/G $ IC C#&&kG //)W%D

+'+OOG$ 	 || 	F77LT=DEE	Frp   c           	      H   0 U l         U R                  R                  5       u  p#UR                  5        H  nUR                   H  nUR
                  nUS::  a  M  [        UR                  5      nUR                  nUR                  n	UR                  n
U R                   R                  U5      nUc  [        XvXU
5      nXR                   U'   M  [        UR                  U5      Ul        [        UR                   U5      Ul        Xl        M     M     [%        5       nUb^  ['        S5        U R(                   HB  nU" UR*                  5      (       a  UR-                  U5        M-  U=R                  S-  sl        MD     O['        S5        U R(                  R/                  U5        g)zEnsure the failed links list is up to date

Based on MS-ADTS 6.2.2.1

:param ping: An oracle function of remote site availability
:return: None
r   Nz6refresh_failed_links: checking if links are still downr&   zdrefresh_failed_links: not checking live links because we
weren't asked to --attempt-live-connections)r>   rC   get_rep_tablesr~   rep_repsFromconsecutive_sync_failuresr\   source_dsa_obj_guidlast_successlast_attempt	dns_name1r;   r   maxfailure_countmintime_first_failurelast_resultr?   r   r@   dns_nameadddifference_update)rL   pingcurrentneededreplica	reps_fromr   r(   r   r   r   frestore_connections
connections                 r+    refresh_failed_links_connections$KCC.refresh_failed_links_connectionsS  sw    !#++446~~'G$11	 ) C C A%y<<=%.%;%;"'44$..))--h79'(:(02A 78))(3&)!//=&IAO+.q/C/C/A,CA($/M) 2 (2 "eJK"99

++,,'++J7,,1, :  @ A 	##556IJr-   c                 *   U R                   R                  [        UR                  5      5      nU(       a^  UR                  S:  aN  [        UR                  5      nX0R                  :  a  [        R                  " S5        U R                  U-
  S:  a  gg)a  Check whether a link to a remote DSA is stale

Used in MS-ADTS 6.2.2.2 Intrasite Connection Creation

Returns True if the remote seems to have been down for at
least two hours, otherwise False.

:param target_dsa: the remote DSA object
:return: True if link is stale, otherwise False
r   z>The last success time attribute for repsFrom is in the future!i   TF)
r>   r;   r\   r(   r   r   r   rG   r!   error)rL   
target_dsafailed_linkunix_first_failures       r+   is_stale_link_connectionKCC.is_stale_link_connection  s     ++//J4G4G0HI((1, > >? # &5LL "> ? MM$66+E r-   c                     g rs   r/   r   s    r+   (remove_unneeded_failed_links_connections,KCC.remove_unneeded_failed_links_connections  s     	r-   c                     U H  nUR                   b  M  U R                  (       aJ  [        R                  " [	        [
        R                  " 5       5      5      Ul         U R                  Ul        Mm  UR                  U R                  5        M     g)a$  Load or fake-load NTDSConnections lacking GUIDs

New connections don't have GUIDs and created times which are
needed for sorting. If we're in read-only mode, we make fake
GUIDs, otherwise we ask SamDB to do it for us.

:param connections: an iterable of NTDSConnection objects.
:return: None
N)r   rI   r   r   r\   uuiduuid4rH   whenCreatedload_connectionrF   )rL   connectionscn_conns      r+   _ensure_connections_are_loaded"KCC._ensure_connections_are_loaded  sX     #G||#==#'99S->#?GL*.++G'++DJJ7 #r-   c                     U R                   R                  R                  5        H;  nUR                  5       nUb  M  [	        U R                   < SU< 35        SUl        M=     g)zFind NTDS Connections that lack a remote

I'm not sure how they appear. Let's be rid of them by marking
them with the to_be_deleted attribute.

:return: None
Nz has phantom connection T)rC   connect_tabler~   get_from_dnstrr    to_be_deleted)rL   r   s_dnstrs      r+   _mark_broken_ntdsconnKCC._mark_broken_ntdsconn  sT     {{00779G,,.G4;;;BD E(,% :r-   c                    U R                   R                  5       (       a  [        SU R                   -  5        gU R                  n U R	                  UR
                  R                  5       5        / nUR
                  R                  5        H  nUR                  5       nX@R                   R                  ;   d  M.  UR                  5       =(       d    UR                  5       (       + n[        UR                  5      nUR                  X4Xe45        M     [!        U5      S:  a  g["        R$                  " US5       H_  u  pxUu  p4peUu  ppU(       a  XJ:X  a  UR&                  U	R&                  :  d#  UR&                  U	R&                  :X  d  MQ  Xk:  d  MX  SUl        Ma     g! [         a    UR                  5       (       a   g GNQf = f)zFind unneeded intrasite NTDS Connections for removal

Based on MS-ADTS 6.2.2.4 Removing Unnecessary Connections.
Every DC removes its own unnecessary intrasite connections.
This function tags them with the to_be_deleted attribute.

:return: None
z>not doing ntdsconn cleanup for site %s, because it is disabledN   T)rE   is_cleanup_ntdsconn_disabledr    rC   r   r   r~   r   is_ror   r}   is_generatedis_rodc_topologyr   r   appendr   	itertoolspermutationsr   r   )rL   mydsalocal_connectionsr   r   	removablepacked_guidabcn_conn2s_dnstr2packed_guid2
removable2s                r+   _mark_unneeded_local_ntdsconn!KCC._mark_unneeded_local_ntdsconn  s    <<4466 .04= >	//0C0C0J0J0LM **113G,,.G,,000!(!5!5!7 "<!(!9!9!;=	&w||4!(('*5*B C 4 !"Q&**+<a@DA784Gk;<8H###h&:&::$$(<(<<+(,% A+  	{{}} 	s   )F G Gc                    U R                   R                  5       (       a  gU R                  R                  n/ nUR	                  5        H  nUR
                  R	                  5        H  nUR                  (       a  M  UR                  5       nUc  M+  XQ;  d  M2  U R                  U5      nUb  SU;   a"  [        R                  " SU-  5        SUl        Mn  UR                  XCU45        M     M     U R                  S U 5       5        U H  u  pGnUR                  5       (       a  UR                  5       (       a  M2  X@R                  ;   a0  U R!                  US5      (       d  U R!                  US5      (       d  Mq  UR"                  nU R$                  R	                  5        H>  n	XR&                  ;   d  M  U H$  u  pnXJLd  M  XR&                  ;   d  M  SUl        M&     M@     M     g)a   find unneeded intersite NTDS Connections for removal

Based on MS-ADTS 6.2.2.4 Removing Unnecessary Connections. The
intersite topology generator removes links for all DCs in its
site. Here we just tag them with the to_be_deleted attribute.

:return: None
N\0ADELz+DSA appears deleted, removing connection %sTc              3   *   #    U  H	  oS    v   M     g7f)r   Nr/   ru   s     r+   rx   8KCC._mark_unneeded_intersite_ntdsconn.<locals>.<genexpr>'  s     +O:NQaD:Ns   )rC   r   rE   r}   r~   r   r   r   r=   r!   infor   r   r   r   rA   is_bridgehead_failed	dsa_dnstrr6   rw_dsa_table)rL   
local_dsasconnections_and_dsasdsacnr   from_dsato_dsa
from_dnstrr   cn2to_dsa2	from_dsa2s                r+   !_mark_unneeded_intersite_ntdsconn%KCC._mark_unneeded_intersite_ntdsconn  s    ;; \\++
!$$&C''..0##++-?,#||G4H'9+?$Q&-%. /+/( (//(0CD 1 '" 	+++O:N+OO$8 B??$$(;(;(=(= +++..vt<<..x>>
 "++J..0!2!223G/iM%):)::/3B, 4H 1 %9r-   c                    UR                  5       (       d  U R                  (       a  UR                  R                  5        H  nUR                  (       a  [
        R                  " SU-  5        UR                  (       a  [
        R                  " SU-  5        UR                  (       d  Mj  [
        R                  " SU-  5        M     UR                  U R                  SS9  g UR                  U R                  5        g )NTO BE DELETED:
%sTO BE ADDED:
%sTO BE MODIFIED:
%sTro)r   rI   r   r~   r   r!   r   to_be_addedto_be_modifiedcommit_connectionsrF   )rL   r   connects      r+   _commit_changesKCC._commit_changes>  s    99;;$--,,335((KK 4w >?&&KK 2W <=)))KK 5 ?@ 6 ""4::$"7 ""4::.r-   c                 (   U R                  5         U R                  5         U R                  R                  5       (       a  U(       a  U R	                  5         U R
                  R                  R                  5        H  nU R                  U5        M     g)zRemove unneeded NTDS Connections once topology is calculated

Based on MS-ADTS 6.2.2.4 Removing Unnecessary Connections

:param all_connected: indicates whether all sites are connected
:return: None
N)	r   r   rC   is_istgr  rE   r}   r~   r  )rL   all_connectedr   s      r+   remove_unneeded_ntdsconnKCC.remove_unneeded_ntdsconnO  sj     	""$**, ;;  ]224<<))002C  % 3r-   c                    UR                   nX`R                  R                  ;   n[        UR                  5      nXR                  :w  a  Xl        UR
                  [        R                  -  S:X  a#  U=R
                  [        R                  -  sl        UR                  5       (       aD  UR
                  [        R                  -  S:X  a#  U=R
                  [        R                  -  sl        U(       d  UR                  U5      (       aD  UR
                  [        R                  -  S:X  a#  U=R
                  [        R                  -  sl        UR                  [        R                  -  S:w  af  UR                  [        R                  -  S:X  aD  UR
                  [        R                   -  S:X  a#  U=R
                  [        R                   -  sl        OKU(       dD  UR
                  [        R                   -  S:X  a#  U=R
                  [        R                   -  sl        U(       de  UR                  [        R"                  -  S:X  aD  UR
                  [        R$                  -  S:X  a#  U=R
                  [        R$                  -  sl        UR                  [        R&                  -  S:w  aD  UR
                  [        R(                  -  S:X  a#  U=R
                  [        R(                  -  sl        UR+                  5       (       d  UR
                  [        R,                  -  S:X  a#  U=R
                  [        R,                  -  sl        UR
                  [        R.                  -  S:X  a#  U=R
                  [        R.                  -  sl        UR0                  < SU R2                  R5                  5       < 3n	UR
                  [        R6                  -  S:w  a$  U=R
                  [        R6                  ) -  sl        [8        R:                  " 5       Ul        UR>                  U	:w  a  Xl        UR@                  S:  a  URB                  U	:w  a  Xl!        URE                  5       (       a  [G        SU-  5        gg)a  Update an repsFrom object if required.

Part of MS-ADTS 6.2.2.5.

Update t_repsFrom if necessary to satisfy requirements. Such
updates are typically required when the IDL_DRSGetNCChanges
server has moved from one site to another--for example, to
enable compression when the server is moved from the
client's site to another site.

The repsFrom.update_flags bit field may be modified
auto-magically if any changes are made here. See
kcc_utils.RepsFromTo for gory details.


:param n_rep: NC replica we need
:param t_repsFrom: repsFrom tuple to modify
:param s_rep: NC replica at source DSA
:param s_dsa: source DSA
:param cn_conn: Local DSA NTDSConnection child

:return: None
r   z._msdcs.r&   zmodify_repsFrom(): %sN)$r   rE   r}   r   schedulereplica_flagsr   DRSUAPI_DRS_ADD_REF!is_schedule_minimum_once_per_weekDRSUAPI_DRS_PER_SYNCis_fsmo_role_ownerDRSUAPI_DRS_INIT_SYNCoptionsr   $NTDSCONN_OPT_OVERRIDE_NOTIFY_DEFAULTNTDSCONN_OPT_USE_NOTIFYDRSUAPI_DRS_NEVER_NOTIFY*NTDSCONN_OPT_DISABLE_INTERSITE_COMPRESSIONDRSUAPI_DRS_USE_COMPRESSIONNTDSCONN_OPT_TWOWAY_SYNCDRSUAPI_DRS_TWOWAY_SYNC
is_enabledDRSUAPI_DRS_DISABLE_AUTO_SYNC!DRSUAPI_DRS_DISABLE_PERIODIC_SYNCr(   rF   forest_dns_nameDRSUAPI_DRS_MAIL_REPr   r   transport_guidr   version	dns_name2is_modifiedr    )
rL   n_rep
t_repsFroms_reps_dsar   r   	same_sitetimesnastrs
             r+   modify_repsFromKCC.modify_repsFroma  s   0 //||555	 .g.>.>?'''"' %%(()-01$$(C(CC$ 4466))--.256((G,H,HH( 0099))../367((G,I,II( __667;>? $">">>3F  --556:=>,,889, ))11269:((G,L,LL( __<<=ADE ))4459<=((G,O,OO( OOd;;;C))001589((G,K,KK( !!##))667;>?((99:( ))::;?BC((==>(~ #(..$**2L2L2NO%%))*.12$$)E)E(EE$$(IIK
! 5(#( #
(<(<(E#( !!##,z9: $r-   c                 b   UR                  5       (       a  UR                  5       (       a  gUR                  5       nU R                  U5      nUc  gUR	                  UR
                  5      nUbA  UR                  5       (       a,  UR                  5       (       a  UR                  5       (       a  U$ g)a  If a connection imply a replica, find the relevant DSA

Given a NC replica and NTDS Connection, determine if the
connection implies a repsFrom tuple should be present from the
source DSA listed in the connection to the naming context. If
it should be, return the DSA; otherwise return None.

Based on part of MS-ADTS 6.2.2.5

:param n_rep: NC replica
:param cn_conn: NTDS Connection
:return: source DSA or None
N)	r(  r   r   r=   get_current_replicanc_dnstr
is_presentr   
is_partial)rL   r1  r   r   r4  r3  s         r+   get_dsa_for_implied_replicaKCC.get_dsa_for_implied_replica0  s    * !!##w'?'?'A'A((*W% =))%..9%"2"2"4"4Lr-   c           	         SnUc  U R                   nUR                  5       (       a  SnUR                  5       (       a  [        S5        g[        S5        UR	                  5       u  p4[        5       nU H  nU(       a  X6   nUR                  U R                  5        UR                   Ho  n[        R                  [        R                  -  [        R                  -  [        R                  -  [        R                  -  n	UR                  U	:w  d  Mi  Xl        Mq     UR!                  U R                  U R"                  S9  M  Xd;  d  M  UR%                  U5        M     [        S['        U5      ['        U5      ['        U5      4-  5        U(       a  [)        SU-  5        U H  nX6	 M     UR+                  5        GH
  n
U
R                  U R                  5        U
R-                  U R                  5        U
R                   GH  n[/        UR0                  5      nU R3                  U5      nUc"  [4        R6                  " S	U-  5        SUl        MO  UR:                  nUR=                  U5      nU H  nUR?                  5       (       a  M    O   SUl        M  URA                  U
RB                  5      nUb?  URE                  5       (       a*  U
R                  5       (       d  URG                  5       (       a	  SUl        M  U RI                  XUX5        GM     URJ                  R+                  5        H  nU RM                  X5      nUc  M  U
R                   H/  n[/        UR0                  5      nXR3                  U5      L d  M-  Sn  O   Uc  M]  [O        U
RB                  5      nURP                  Ul        URA                  U
RB                  5      nU RI                  XUX5        URS                  5       (       d  M  U
R                  RU                  U5        M     U R"                  (       d  U(       a}  U
RW                  5       nU(       a  [4        RX                  " S
U-  5        U
R[                  5       nU(       a  [4        RX                  " SU-  5        U
R!                  U R                  SS9  GM  U
R!                  U R                  5        GM     U(       a  gUR+                  5        GHl  n
U
R]                  U R                  5        U
R^                   H  n[/        UR0                  5      nU R3                  U5      nUc"  [4        R6                  " SU-  5        SUl        MN  UR:                  nSU;   a"  [4        R6                  " SU-  5        SUl        M  UR=                  U R`                  5      n['        U5      S:  a  M  SUl        M     U R"                  (       a\  U
R^                   H/  nUR8                  (       d  M  [4        RX                  " SU-  5        M1     U
Rc                  U R                  SS9  GMQ  U
Rc                  U R                  5        GMo     g)a#  Adjust repsFrom to match NTDSConnections

This function adjusts values of repsFrom abstract attributes of NC
replicas on the local DC to match those implied by
nTDSConnection objects.

Based on [MS-ADTS] 6.2.2.5

:param current_dsa: optional DSA on whose behalf we are acting.
:return: None
FNTz;skipping translate_ntdsconn() because disabling flag is setztranslate_ntdsconn(): enterr  zcurrent %d needed %d delete %dzdeleting these reps: %sz'repsFrom source DSA guid (%s) not foundr  r
  z%repsTo source DSA guid (%s) not foundr   z+repsTo source DSA guid (%s) appears deletedr   zREMOVING REPS-TO: %s)2rC   r   is_translate_ntdsconn_disabledr    r   r?   load_repsFromrF   r   r   r  r  r  %DRSUAPI_DRS_SPECIAL_SECRET_PROCESSINGDRSUAPI_DRS_NONGC_RO_REPr  commit_repsFromrI   r   r   r   r~   load_fsmo_rolesr\   r   r<   r!   r`   r   r   get_connection_by_from_dnstrr   r;  r<  r=  r>  r8  r   r?  r   r(   r0  r   dumpstr_to_be_deletedr   dumpstr_to_be_modifiedload_repsTo
rep_repsTorB   commit_repsTo)rL   current_dsar  current_rep_tableneeded_rep_tabledelete_repsrf   c_repr2  r  r1  guidstrr4  r   r   r   r3  textt_repsTorts                       r+   translate_ntdsconnKCC.translate_ntdsconnW  s    ++KB5577 5 6./.9.H.H.J+ e" 'E)0##DJJ/"'"4"4J%,%B%B%,%A%A&B%,%@%@&A &-%R%R&S &-%E%E	&FM
 "//=@3@0 #5 %%djjT]]%C0OOE*! '$ 	1S9J5K%&K(85: : 	; +k9:$%, % &,,.E 

+!!$**-
 $00
 j<<=//8 =NN#L#*$+ ,/3J,
  //)FFwO*G"3355  +
 04J, 11%..A=(8(8(:(:%*:*:*<*</3J, $$UuN[ 1d '44;;=88H= #("4"4J!*"@"@AG 7 7 @@ $	 #5 = (7
16
.11%..A$$UuN ))++&&--j9? >B }}224KK 4t ;<335KK 5 <= %%djjT%: %%djj1W /h %,,.E djj)
 ",, h::;//8 =NN#J#*$+ ,-1H*
  //'NN#P#*$+ ,-1H*#@@ARARS{#a' .2H*? -B }}**B'''$:R$?@ + ##DJJ4#8 ##DJJ/k /r-   c                 N    Ub  [         R                  " S5        g[        S5        g)a  Merge of kCCFailedLinks and kCCFailedLinks from bridgeheads.

The KCC on a writable DC attempts to merge the link and connection
failure information from bridgehead DCs in its own site to help it
identify failed bridgehead DCs.

Based on MS-ADTS 6.2.2.3.2 "Merge of kCCFailedLinks and kCCFailedLinks
from Bridgeheads"

:param ping: An oracle of current bridgehead availability
:return: None
Nz'merge_failed_links() is NOT IMPLEMENTEDz}skipping merge_failed_links() because it requires real network connections
and we weren't asked to --attempt-live-connections)r"   	DEBUG_REDr    )rL   r   s     r+   merge_failed_linksKCC.merge_failed_linksV  s&    $ OOEF J Kr-   c                 t   U R                   R                  S-  S:g  n[        U R                  R                  5      n[        XR                  UU R                  U5      nU R                  (       d  U R                  b  / nUR                   Hh  n[        R                  " UR                  S5       H@  u  pxUR                  UR                  R                   UR                  R                   45        MB     Mj     Sn	SUR"                  -  n
[%        XSU R&                  U	[(        U R                  U R                  S9  U$ )a  Set up an intersite graph

An intersite graph has a Vertex for each site object, a
MultiEdge for each SiteLink object, and a MutliEdgeSet for
each siteLinkBridge object (or implied siteLinkBridge). It
reflects the intersite topology in a slightly more abstract
graph form.

Roughly corresponds to MS-ADTS 6.2.2.3.4.3

:param part: a Partition object
:returns: an InterSiteGraph object
i  r   r   r/   zsite_edges_%sFdirectedlabel
propertiesr"   rJ   rK   )rE   site_optionsr\   r7   r   r   r6   r8   rJ   rK   edgesr   combinationsverticesr   r   
site_dnstrr   r   rB   r   )rL   r   bridges_requiredr-  g	dot_edgesedger   r   verify_propertiesr_   s              r+   r   KCC.setup_grapho  s   &  <<44zAQFT..334oo~++-=? ;;$++7I%224==!DDA$$aff&7&79J9J%KL E   !#"T\\1D4U!%!2!2&7u"&++(,(9(9	; r-   c                     U R                  XUXE5      nU(       d$  [        R                  " SUR                  -  5        g[        R                  " SUR                  < SUS   R
                  < 35        US   $ )aH  Get a bridghead DC for a site.

Part of MS-ADTS 6.2.2.3.4.4

:param site: site object representing for which a bridgehead
    DC is desired.
:param part: crossRef for NC to replicate.
:param transport: interSiteTransport object for replication
    traffic.
:param partial_ok: True if a DC containing a partial
    replica or a full replica will suffice, False if only
    a full replica will suffice.
:param detect_failed: True to detect failed DCs and route
    replication traffic around them, False to assume no DC
    has failed.
:return: dsa object for the bridgehead DC or None
z"get_bridgehead FAILED:
sitedn = %sNzget_bridgehead:
	sitedn = z	
	bhdn = r   )get_all_bridgeheadsr"   DEBUG_MAGENTArf  DEBUG_GREENr   )rL   r   r   rg   
partial_okdetect_failedbhss          r+   get_bridgeheadKCC.get_bridgehead  sn    & &&t9'1B E $!0 1??CF,<,<> 	?1vr-   c                    / nUR                   S:w  a  [        SUR                   < 35      e[        UR                  5        UR                  R	                  5        GH  nUR                  5       n[        UR                  5      S:w  a  XR                  ;  a  M>  U R                  R                  U5      (       aG  UR                  U5      u  pnU	(       a  U(       a	  U(       d  M  UR                  UR                  5      nO<UR                  UR                  5      nUb  UR                  5       (       a	  U(       d  M  U R                  R                  5       (       a?  Ub<  UR!                  5       (       a'  UR#                  [$        R&                  5      (       d  GM?  U R)                  Xu5      (       a  [+        S5        GMc  [        SUR,                  -  5        UR/                  U5        GM     UR1                  5       (       a  UR3                  [5        [6        5      S9  O[8        R:                  " U5        [<        R>                  " U5        U$ )ax  Get all bridghead DCs on a site satisfying the given criteria

Part of MS-ADTS 6.2.2.3.4.4

:param site: site object representing the site for which
    bridgehead DCs are desired.
:param part: partition for NC to replicate.
:param transport: interSiteTransport object for
    replication traffic.
:param partial_ok: True if a DC containing a partial
    replica or a full replica will suffice, False if
    only a full replica will suffice.
:param detect_failed: True to detect failed DCs and route
    replication traffic around them, FALSE to assume
    no DC has failed.
:return: list of dsa object for available bridgehead DCs
rT   z5get_all_bridgeheads has run into a non-IP transport! r   zbridgehead is failedzfound a bridgehead: %skey) r_   r   r    r   r~   get_parent_dnstrr   bridgehead_listrE   r5  should_be_presentr;  r<  r>  rC   r   
is_defaultis_minimum_behaviorr   DS_DOMAIN_FUNCTION_2008r   r   r   r   is_random_bridgehead_disabledsortr   r,   randomshuffler"   DEBUG_YELLOW)rL   r   r   rg   rq  rr  rs  r   pdnstrr   r  partialreps                r+   rn  KCC.get_all_bridgeheads  s   & >>T!'nn/ 0 0 	""#$$++-C))+F
 Y../14888 ||%%c**&*&<&<S&A#G'*--dmm< --dmm<;3>>#3#3J {{  ""s3>>;K;K..t/K/KLL ((<<,--=>JJsO_ .n --//HH$;<H=NN33
r-   c                 r    U(       d  gU R                   R                  S-  (       a  gU R                  U5      $ )a  Determine whether a given DC is known to be in a failed state

    :param dsa: the bridgehead to test
    :param detect_failed: True to really check, False to assume no failure
    :return: True if and only if the DC should be considered failed

    Here we DEPART from the pseudo code spec which appears to be
    wrong. It says, in full:

/***** BridgeheadDCFailed *****/
/* Determine whether a given DC is known to be in a failed state.
 * IN: objectGUID - objectGUID of the DC's nTDSDSA object.
 * IN: detectFailedDCs - TRUE if and only failed DC detection is
 *     enabled.
 * RETURNS: TRUE if and only if the DC should be considered to be in a
 *          failed state.
 */
BridgeheadDCFailed(IN GUID objectGUID, IN bool detectFailedDCs) : bool
{
    IF bit NTDSSETTINGS_OPT_IS_TOPL_DETECT_STALE_DISABLED is set in
    the options attribute of the site settings object for the local
    DC's site
        RETURN FALSE
    ELSEIF a tuple z exists in the kCCFailedLinks or
    kCCFailedConnections variables such that z.UUIDDsa =
    objectGUID, z.FailureCount > 1, and the current time -
    z.TimeFirstFailure > 2 hours
        RETURN TRUE
    ELSE
        RETURN detectFailedDCs
    ENDIF
}

    where you will see detectFailedDCs is not behaving as
    advertised -- it is acting as a default return code in the
    event that a failure is not detected, not a switch turning
    detection on or off. Elsewhere the documentation seems to
    concur with the comment rather than the code.
    F   )rE   rb  r   )rL   r   rr  s      r+   r   KCC.is_bridgehead_failed  s3    P 
 <<$$z1,,S11r-   c           	      $   U R                  X1UU	S5      n[        S U 5       5      n[        R                  " S[	        U5      < SU Vs/ s H  oR
                  PM     sn< 35        U R                  XaUU	S5      nUR                  5       (       a  UR                  U5        [        R                  " S[	        U5      < SU Vs/ s H  oR
                  PM     sn< 35        U GH  nUR                  R                  5        GH  nUR                  UR                  5      nUc  M$  [        R                  " SUR
                  -  5        UR                  5       (       d  M^  UR                  5       (       a  Mu  UR                  UR                   :X  d  M  UR#                  5       (       d.  UR%                  U5      (       d  UUl        UR)                  S5        UR+                  5       (       as  UR-                  5       (       a^  U[.        R0                  -  S	:X  aF  U=R2                  [.        R4                  [.        R6                  -  ) -  sl        UR)                  S5        O\U[.        R0                  -  S	:w  aE  U=R2                  [.        R4                  [.        R6                  -  -  sl        UR)                  S5        UR9                  5       (       aM  U[.        R:                  -  S	:X  a5  U=R2                  [.        R<                  ) -  sl        UR)                  S5        OKU[.        R:                  -  S	:w  a4  U=R2                  [.        R<                  -  sl        UR)                  S5        UR?                  5       (       aM  U[.        R@                  -  S	:X  a5  U=R2                  [.        RB                  ) -  sl        UR)                  S5        OKU[.        R@                  -  S	:w  a4  U=R2                  [.        RB                  -  sl        UR)                  S5        U RD                  (       d  UR                  5       (       aG  URF                  (       a  [H        RJ                  " S
U-  5        URM                  U RN                  SS9  GM  URM                  U RN                  5        GM     GM     S	nU H  nUR                  R                  5        H  nUR                  UR                  5      nUc  M#  [        R                  " SUR
                  -  5        UR                  5       (       a  UR                  UR                   :X  d  Mw  UR                  5       (       a  M  U RQ                  UU
5      (       d  U RQ                  X5      (       d  US-  nU RR                  RU                  U5        M     M     [        RV                  " SU-  5        [Y        SU RR                  < 35        US	:X  Ga  [.        RZ                  nU[.        R0                  -  S	:w  a$  U[.        R4                  [.        R6                  -  -  nU[.        R:                  -  S	:w  a  U[.        R<                  -  nU[.        R@                  -  S	:w  a  U[.        RB                  -  n[]        SU R^                  R
                  -  5        [.        R`                  [.        Rb                  -  nURe                  UUUUR
                  U5      nU RD                  (       d  UR                  5       (       aE  URf                  (       a  [H        RJ                  " SU-  5        URM                  U RN                  SS9  OURM                  U RN                  5        U RR                  RU                  U5        ggs  snf s  snf )a  Create an nTDSConnection object as specified if it doesn't exist.

Part of MS-ADTS 6.2.2.3.4.5

:param part: crossRef object for the NC to replicate.
:param rbh: nTDSDSA object for DC to act as the
    IDL_DRSGetNCChanges server (which is in a site other
    than the local DC's site).
:param rsite: site of the rbh
:param transport: interSiteTransport object for the transport
    to use for replication traffic.
:param lbh: nTDSDSA object for DC to act as the
    IDL_DRSGetNCChanges client (which is in the local DC's site).
:param lsite: site of the lbh
:param link_opt: Replication parameters (aggregated siteLink options,
                                         etc.)
:param link_sched: Schedule specifying the times at which
    to begin replicating.
:partial_ok: True if bridgehead DCs containing partial
    replicas of the NC are acceptable.
:param detect_failed: True to detect failed DCs and route
    replication traffic around them, FALSE to assume no DC
    has failed.
Fc              3   <   #    U  H  oR                   U4v   M     g 7frs   r   ru   s     r+   rx   (KCC.create_connection.<locals>.<genexpr>^  s     <8a++q)8s   z
rbhs_all:  z
lbhs_all: Nz
rdsa is %sTr   r
  r  zround 2: rdsa is %sr&   zvalid connections %dzkept_connections:
znew connection, KCC dsa: %sr	  )4rn  dictr"   
DEBUG_GREYr   r   r   r   r   r~   r;   r  r   r   r   r-  r   is_user_owned_scheduleis_equivalent_scheduler  set_modifiedis_override_notify_defaultis_use_notifyr   NTDSSITELINK_OPT_USE_NOTIFYr   r!  r"  is_twoway_syncNTDSSITELINK_OPT_TWOWAY_SYNCr&  !is_intersite_compression_disabled$NTDSSITELINK_OPT_DISABLE_COMPRESSIONr$  rI   r  r!   r   r  rF   r   rA   r   rZ  r   NTDSCONN_OPT_IS_GENERATEDr    rC   SYSTEM_FLAG_CONFIG_ALLOW_RENAMESYSTEM_FLAG_CONFIG_ALLOW_MOVEnew_connectionr  )rL   r   rbhrsiterg   lbhlsitelink_opt
link_schedrq  rr  rbhs_all	rbh_tablerw   lbhs_allldsar   rdsavalid_connectionsoptsystem_flagss                        r+   create_connectionKCC.create_connectionA  s	   6 ++E,6?<8<<	c(mDL.MHq{{H.MO 	P ++E,6?99;;OOC c(mDL.MHq{{H.MO 	P D((//1 }}R]]3<''t~~(EF __&&,,..&&)..8  668866zBB&0- 4466'')) %t'G'GGAMJJ"&"K"K"&">">#? !@@J OOD1 %t'G'GGAMJJ!%!J!J!%!=!=">?J OOD1 ((** %t'H'HHQNJJ4+H+H*HHJOOD1 %t'H'HHQNJJ$*G*GGJOOD1 ;;== &!FFGKLMJJ!%!P!P PQJOOD1 &!FFGKLMJJ $ O OPJOOD1 }}

,,"KK(=(BC//

t/D//

;] 2 d  D((//1 }}R]]3<''(=(NO
 //++''9>>9,,.. "66t]KK!66tKK)Q.) ))--b19 2 @ 	.1BBC)>)>@A! 00C
 4;;;AAA445 6
 4<<<Bt444
 ::;?@AtFFF 2T[[5J5JJK @@ >>?L ##Cy$'MM:?B }}		>>KK 2R 78&&tzzd&;&&tzz2 !!%%b)[ "[ /N /Ns   	^^c                 ^   / Ul         / Ul        SnXR                  ;   a  [        U R                  R
                  5      nU R                  UR                  UR                  U R                  UR                  5       U5      nUc>  UR                  R                  5       (       a  UR                   R                  U5        O9SnO6UR                   R                  U5        UR                  R                  U5        UR                   R                  S5        UR                  R                  S5        U$ )a&  Build a Vertex's transport lists

Each vertex has accept_red_red and accept_black lists that
list what transports they accept under various conditions. The
only transport that is ever accepted is IP, and a dummy extra
transport called "EDGE_TYPE_ALL".

Part of MS-ADTS 6.2.2.3.4.3 -- ColorVertices

:param vertex: the remote vertex we are thinking about
:param local_vertex: the vertex relating to the local site.
:param graph: the intersite graph
:param detect_failed: whether to detect failed links
:return: True if some bridgeheads were not found
FTEDGE_TYPE_ALL)accept_red_redaccept_blackconnected_verticesr\   r7   r   rt  r   r   is_blackis_rodc_siter   )rL   vertexlocal_vertexgraphrr  found_failedt_guidbhs           r+   add_transportsKCC.add_transports=  s    2 !# ---**//0F$$V[[&++%)%6%6%+__%6GB z;;++--))008#'L%%,,V4##**62 	$$_5""?3r-   c                    SnSn[        SUR                  < SU< 35        [        U R                  U5      nUR	                  5         UR
                   H.  nUR	                  5         U R                  XvX5      (       d  M,  SnM0     UR                  5       (       a  XE4$ [        UU R                  UR                  S9u  p[        SUR                  U	4-  5        U	S:  a  SnUR                  5       n
U R                  n[        SU-  5        U GH  nUR                  (       a(  UR
                  S	   R                  U R                  L a  M=  UR
                  S	   R                  U R                  L a  UR
                  S   R                  nOUR
                  S	   R                  nXR                  L a  [        S
5        M  U R                  XUX5      nUc  M  U R                   R#                  5       (       a  U R                  nU R                   nOU R                  nU R                  XUX5      nUc  [$        R&                  " S5          g[        SU< SU< 35        [        SUR
                  < 35        [$        R(                  " SU< SU< SS< 35        UR*                  nUc  S	nSnOUR,                  nUR.                  nU R1                  X.XUUUUX5
        GM     XE4$ )a  Create intersite NTDSConnections as needed by a partition

Construct an NC replica graph for the NC identified by
the given crossRef, then create any additional nTDSConnection
objects required.

:param graph: site graph.
:param part: crossRef object for NC.
:param detect_failed:  True to detect failed DCs and route
    replication traffic around them, False to assume no DC
    has failed.

Modifies self.kept_connections by adding any connections
deemed to be "in use".

:return: (all_connected, found_failed_dc)
(all_connected) True if the resulting NC replica graph
    connects all sites that need to be connected.
(found_failed_dc) True if one or more failed DCs were
    detected.
TFz$create_connections(): enter
	partdn=z
	detect_failed=)r`  z%s Number of components: %dr&   zedge_list %sr   zrsite is my_siteNzDISASTER! lbh is None)FTzlsite: z
rsite: z	vertices zbridgeheads

zF----------------------------------------------------------------------)r    r<  r   rE   color_vertexre  r  is_whiter   r   r  r7   r   r_  r   rt  rC   r   r"   rZ  
DEBUG_BLUE	site_linkr   r  r  )rL   r  r   rr  r  r  	my_vertexv	edge_listn_componentsrq  rg   r   r  r  r  r  rm   r  r  s                       r+   create_connectionsKCC.create_connectionso  s   , --0 	1 4<<.	 ANN""1FF#    .."9%:>,,@D#N	 	.--./ 	0!!M '')
 %%	ny()Azzajjm00DLL@zz!}!!T\\1

1**

1** $() %%e9&0AC{ {{  ""kk))%y*4E { 78"ue<=ajj23#sHMN{{H!
#++%..
""4e#&x#->i p **r-   c                    Sn[        5       U l        U R                  R                  5        H  nUR	                  5       (       d  M  UR                  5       (       a  M1  U R                  U5      nSnU R                  UUS5      u  pT[        SU< SU< 35        U(       a  Mu  SnU(       d  M  U R                  X2S5        M     U$ )a  Create NTDSConnections as necessary for all partitions.

Computes an NC replica graph for each NC replica that "should be
present" on the local DC or "is present" on any DC in the same site
as the local DC. For each edge directed to an NC replica on such a
DC from an NC replica on a DC in another site, the KCC creates an
nTDSConnection object to imply that edge if one does not already
exist.

Modifies self.kept_connections - A set of nTDSConnection
objects for edges that are directed
to the local DC's site in one or more NC replica graphs.

:return: True if spanning trees were created for all NC replica
         graphs, otherwise False.
TFzwith detect_failed: connected z Found failed )	r?   rA   r5   r~   r(  
is_foreignr   r  r   )rL   r  r   r  r  	connecteds         r+   create_intersite_connections KCC.create_intersite_connections  s    "  # OO**,D??$$  $$T*E !L&*&=&=e>BD'J#I l, -9 %< ++E?3 -6 r-   c                    U R                   nU R                  nSn[        S5        U R                  (       a  UR	                  U R
                  USS9  OUR	                  U R
                  USS9  UR                  5       (       a  [        SU-  5        U$ UR                  5       (       d  [        SU-  5        U$ U R                  U5        U R                  5       n[        SU-  5        U$ )a  Generate the inter-site KCC replica graph and nTDSConnections

As per MS-ADTS 6.2.2.3.

If self.readonly is False, the connections are added to self.samdb.

Produces self.kept_connections which is a set of NTDS
Connections that should be kept during subsequent pruning
process.

After this has run, all sites should be connected in a minimum
spanning tree.

:param ping: An oracle function of remote site availability
:return (True or False):  (True) if the produced NC replica
    graph connects all sites that need to be connected
Tzintersite(): enterr  Fz+intersite(): exit disabled all_connected=%dz+intersite(): exit not istg all_connected=%dz"intersite(): exit all_connected=%d)
rC   rE   r    rI   select_istgrF   is_intersite_topology_disabledr  r[  r  )rL   r   r   mysiter  s        r+   	intersiteKCC.intersite%  s    ( %& ==tzz5T:tzz5U; 0022B"# $  }}B"# $  % 99;5EFr-   c                    U R                   R                  5       (       d  gU R                   R                  R                  5       nU Vs/ s H  o3R	                  5       (       d  M  UPM     nnU Vs/ s H  nX4;  d  M
  UPM     nnU(       ad  U(       a\  U H1  nUS   nUR
                  Ul        UR                  Ul        SUl        M3     U R                   R                  U R                  US9  gggs  snf s  snf )z_Updates the RODC NTFRS connection object.

If the local DSA is not an RODC, this does nothing.
Nr   Tr  )
rC   r   r   r~   r   r  r  r  r  rF   )rL   r  all_connectionsrw   ro_connectionsrw_connectionsconr  s           r+   update_rodc_connectionKCC.update_rodc_connection`  s    
 {{  "" ++33::<%4M_8J8J8L!_M%4 6_4 _ 6 n%$Q'!$"||%)"	 & KK**4::"*= -> N6s   	C2%C21	C7>C7c                 \    Sn USX"-  -  SU-  -   S-   ::  a  OUS-   nM  US-   nUS:  a  U$ g)a  Find the maximum number of edges directed to an intrasite node

The KCC does not create more than 50 edges directed to a
single DC. To optimize replication, we compute that each node
should have n+2 total edges directed to it such that (n) is
the smallest non-negative integer satisfying
(node_count <= 2*(n*n) + 6*n + 7)

(If the number of edges is m (i.e. n + 2), that is the same as
2 * m*m - 2 * m + 3). We think in terms of n because that is
the number of extra connections over the double directed ring
that exists by default.

edges  n   nodecount
  2    0    7
  3    1   15
  4    2   27
  5    3   43
          ...
 50   48 4903

:param node_count: total number of nodes in the replica graph

The intention is that there should be no more than 3 hops
between any two DSAs at a site. With up to 7 nodes the 2 edges
of the ring are enough; any configuration of extra edges with
8 nodes will be enough. It is less clear that the 3 hop
guarantee holds at e.g. 15 nodes in degenerate cases, but
those are quite unlikely given the extra edges are randomly
arranged.

:param node_count: the number of nodes in the site
"return: The desired maximum number of connections
r   r         r&   2   r/   )rL   
node_countns      r+   intrasite_max_node_edgesKCC.intrasite_max_node_edges  sT    F a15kQU3a78AA  Er6Hr-   c                 n  ^  UR                  U5      u  pgn[        R                  " SSU-  -   SU-  -   SU-  -   SU-  -   SU-  -   SU-  -   5        U(       d$  [        R                  " SUR                  -  5        g	[        X#R                  5      n	U	R                  T R                  5        Xl        Xyl	        UR                  U	5        / n
T R                  R                  R                  5        GH#  nUR                  UR                  ;  a  M   UR                  UR                     nUR                  5       (       a  MP  UR!                  5       (       d  Mg  UR                  5       (       d  XL a  M  U(       a  UR#                  5       (       d  M  U(       aK  U(       dD  UR$                  [&        R(                  :X  a&  UR+                  [,        R.                  5      (       d  M  U(       a  T R1                  U5      (       a  GM  U
R3                  U5        GM&     U(       a  T R                  R                  R                  5        H  nUR                  UR                  ;  a  M  UR                  UR                     nUR5                  5       (       d  MO  UR!                  5       (       d  Mf  UR                  5       (       d  XL a  M  U(       a  UR#                  5       (       d  M  U(       a  T R1                  U5      (       a  M  U
R3                  U5        M     U
R3                  U	5        U
R7                  S
 S9  [9        U
5      nT R;                  U5      n/ nU
 H*  n[=        UR>                  U5      nUR3                  U5        M,     SnUUS-
  :  a  U
U   R5                  5       (       a  U
US-      R5                  5       (       a$  UUS-      RA                  U
U   R>                  5        U
US-      R5                  5       (       a  U
U   R5                  5       (       a$  UU   RA                  U
US-      R>                  5        US-   nUUS-
  :  a  M  XS-
     R5                  5       (       a  U
S   R5                  5       (       a#  US   RA                  XS-
     R>                  5        U
S   R5                  5       (       a  XS-
     R5                  5       (       a$  UUS-
     RA                  U
S   R>                  5        [C        S[9        U
5      -  5        [C        SRE                  S U
 5       5      5        T RF                  S	L=(       a    T R                  nT RH                  (       d  U(       Gae  / n[K        5       nU H_  nURM                  URN                  5        URP                   H1  nUR3                  UURN                  45        URM                  U5        M3     Ma     Sn[S        SUUURT                  < S[V        UR$                     < SUR                  < 3U[B        T RH                  T RF                  SS9	  [K        U 4S jU 5       5      nU VVs/ s H  u  nnUU;   d  M  UU;   d  M  UU4PM     nnnSn[S        SUUURT                  < S[V        UR$                     < SUR                  < 3U[B        T RH                  T RF                  SS9	  U H  nT R                  R                  URN                     n U RX                  R                  5        H<  n!U!RZ                  n"U"T R                  R                  ;   d  M+  URA                  U"5        M>     M     [C        SSRE                  S U
 5       5      -  5        [C        SSRE                  S U 5       5      -  5        U GH  n#US:  Gaj  U#R]                  5       (       GdT  U V$s/ s H(  n$U$U#Ld  M
  U$RN                  U#RP                  ;  d  M&  U$PM*     n%n$[        R^                  " SU#RN                  U[9        U5      [9        U%5      4-  5        [C        S U% V$s/ s H  n$U$RN                  PM     sn$-  5        U%(       a  U#R]                  5       (       d  [`        Rb                  " U%5      n&[C        S!U&RN                  -  5        U#RA                  U&RN                  5      (       d#  [        R                  " S"U&RN                  -  5        U%Re                  U&5        U%(       a  U#R]                  5       (       d  M  OB[g        S#U#RN                  < S$U< S%[9        U#RP                  5      < S&U#Rh                  < 35        [g        S'U#-  5        U#RN                  URN                  :X  d  GM  U#Rk                  UT Rl                  5        GM     T RH                  (       d  U(       Gaf  / n[K        5       nU H_  nURM                  URN                  5        URP                   H1  nUR3                  UURN                  45        URM                  U5        M3     Ma     Sn[S        S(UUURT                  < S[V        UR$                     < SUR                  < 3U[B        T RH                  T RF                  SS9	  [K        U 4S) jU 5       5      nU VVs/ s H  u  nnUU;   d  M  UU;   d  M  UU4PM     nnnSn[S        S*UUURT                  < S[V        UR$                     < SUR                  < 3U[B        T RH                  T RF                  SS9	  g	g	s  snnf s  sn$f s  sn$f s  snnf )+a  Create an intrasite graph using given parameters

This might be called a number of times per site with different
parameters.

Based on [MS-ADTS] 6.2.2.2

:param site_local: site for which we are working
:param dc_local: local DC that potentially needs a replica
:param nc_x:  naming context (x) that we are testing if it
            "should be present" on the local DC
:param gc_only: Boolean - only consider global catalog servers
:param detect_stale: Boolean - check whether links seems down
:return: None
z"construct_intrasite_graph(): enterz
	gc_only=%dz
	detect_stale=%dz
	needed=%sz
	ro=%sz
	partial=%sz
%szH%s lacks 'should be present' status, aborting construct_intrasite_graph!Nc                 ,    [        U R                  5      $ rs   )r   rep_dsa_guid)r  s    r+   <lambda>/KCC.construct_intrasite_graph.<locals>.<lambda>  s    HS-=-=$>r-   rw  r   r&   zr_list is length %sr  c              3   d   #    U  H&  n[        UR                  UR                  45      v   M(     g 7frs   )r\   r  rep_dsa_dnstrru   s     r+   rx   0KCC.construct_intrasite_graph.<locals>.<genexpr>  s,      )!'A Q^^Q__=>>!'s   .0r  intrasite_pre_ntdscon__T)r`  ra  r"   rJ   rK   r_  c              3   t   >#    U  H-  nTR                  U5      R                  5       (       a  M)  Uv   M/     g 7frs   r=   r   rv   rw   rL   s     r+   rx   r    -      "B\)-a)>)>)@ #$!\   (8	8)r  directed_double_ring_or_smallintrasite_rw_pre_ntdsconzreps are:  %sz   c              3   8   #    U  H  oR                   v   M     g 7frs   )r  ru   s     r+   rx   r    s     *KFq??F   zdsas are:  %sc              3   8   #    U  H  oR                   v   M     g 7frs   r  ru   s     r+   rx   r    s     *K
1;;
r     zDlooking for random link for %s. r_len %d, graph len %d candidates %dzcandidates %sztrying to add candidate %szcould not add %sznot adding links to z: nodes z, links is /z%sintrasite_post_ntdsconc              3   t   >#    U  H-  nTR                  U5      R                  5       (       a  M)  Uv   M/     g 7frs   r  r  s     r+   rx   r  '	  r  r  intrasite_rw_post_ntdscon)7r{  r"   r  rZ  r<  r   identify_by_basednrF   rep_partialrep_roadd_needed_replicarE   r}   r~   rO  r   r=  r'   nc_typer   domainr}  r   r~  r   r   r>  r  r   r  r   r  add_edge_fromr   joinrK   rJ   r?   r   r   	edge_fromr   rf  r   r   r  has_sufficient_edgesr  r  choiceremover    	max_edgesadd_connections_from_edgesr7   )'rL   
site_localdc_localnc_xgc_onlydetect_staler   r  r  l_of_xr_listdc_sf_of_xp_of_xr_lenmax_node_edges
graph_listr  nodeido_dot_filesri  dot_verticesv1v2rk  rw_dot_verticesr   r   rw_dot_edgesrw_verify_propertiesr  r   r  remotetnoderw   
candidatesothers'   `                                      r+   construct_intrasite_graphKCC.construct_intrasite_graph  s	   F #44X>G?+g560<?@ +V34 '+	,
 ,g56 "D=) 	* OO B MM* +  8]]3!!$**-$ 	##F+0  LL**113D }}D$:$:: ++DMM:F ||~~
 $$&&
 zz||t/
 tzz||( 'dllfmm&C//0L0LMM
  = =d C C MM&!} 4X  ..557
 ==(>(>> //> ((**
 ((**
 ::<<4#3
 4::<<
  D$A$A$$G$G f%U 8\ 	f>?F66u= 
CS..?Dd# 
 519o !9''))VAqD\-D-D-F-F1q5!//q	0G0GH !a%=++--1E1E1G1G1++F1q5M,G,GHAA 519o ai ++--1E1E1G1GqM''qy(9(G(GH ay##%%q)9)D)D)F)Fuqy!//q	0G0GH#c&k12dii )!') ) 	* ((4C;;,I5L   .,,B$$b",,%78 $$R( ' ! !/2I|1;1F1F1;DLL1I15"@ '8u"&++(,(9(9$(* " "B\ "B BO/8 Kytq!0 #56/5I #QFyL K$E 5|*1;1F1F1;DLL1I15"@ ';%"&++(,(9(9$(* !F,,(()9)9:C,,335 ++T\\333((0 6 ! 	o

*KF*K KKLo

*K
*K KKLE z%"<"<">">)3 DA ~   {{%//A  
 D    ">$)OOUC
O$'
O$5"5 6
 oj(Ijj(IIJ )C)C)E)E"MM*5E6HI ..u??(:U__(LM%%e, !)C)C)E)E //5#eoo2F//+ ,
 TE\"
 ("4"44004;L;LMY  \ ;;,I5L   .,,B$$b",,%78 $$R( ' ! !/3Y1;1F1F1;DLL1I15"@ '8u"&++(,(9(9$(* " "B\ "B BO/8 Kytq!0 #56/5I #QFyL K$E 6*1;1F1F1;DLL1I15"@ ';%"&++(,(9(9$(*3 'UKVD )JVKs<   l! l!(l!	l'l',l'7l, l11l19l1c                    U R                   n[        S5        U R                  nUR                  5       (       a  gUR	                  5       (       + nUR
                  R                  5        H/  nUR                  (       d  M  [        R                  " SU-  5        M1     U R                  R                  5        Hf  u  pVU R                  X!USU5        UR
                  R                  5        H/  nUR                  (       d  M  [        R                  " SU-  5        M1     Mh     UR
                  R                  5        H/  nUR                  (       d  M  [        R                  " SU-  5        M1     U R                  R                  5        H0  u  pVUR                  5       (       d  M  U R                  X!USU5        M2     UR
                  R                  5        H/  nUR                  (       d  M  [        R                  " SU-  5        M1     U R                  R                  5        H  u  pVU R                  X!USS5        M     UR
                  R                  5        H/  nUR                  (       d  M  [        R                   " SU-  5        M1     U R                  R                  5        H0  u  pVUR                  5       (       d  M  U R                  X!USS5        M2     U R#                  U5        g)aq  Generate the intrasite KCC connections

As per MS-ADTS 6.2.2.2.

If self.readonly is False, the connections are added to self.samdb.

After this call, all DCs in each site with more than 3 DCs
should be connected in a bidirectional ring. If a site has 2
DCs, they will bidirectionally connected. Sites with many DCs
may have arbitrary extra connections.

:return: None
zintrasite(): enterNr	  FT)rC   r    rE   is_intrasite_topology_disabledis_detect_stale_disabledr   r~   r  r"   
DEBUG_CYANr5   itemsr'  r  r  	is_configrZ  r  )rL   r   r  r  r  partdnr   s          r+   	intrasiteKCC.intrasite7	  sW    %& 0022";;==**113G"""  !3g!=> 4
 !OO113LF**6$+79 ..557&&&$$%7'%AB 8 4 **113G"""""#5#?@ 4
 !OO113LF~~..vdD/;= 4 **113G"""  !3g!=> 4
 !OO113LF**6$+02 4 **113G""" 2W <= 4 !OO113LF~~..vdD/46 4
 	U#r-   c                    U R                  5         U R                  5         U R                  5         U R                  5         U R	                  5         U R                  5         / nU R                  R                  5        HX  nUR                  UR                  R                  5        Vs/ s H   nUR                  R                  SSS5      PM"     sn5        MZ     U$ s  snf )zCompile a comprehensive list of DSA DNs

These are all the DSAs on all the sites that KCC would be
dealing with.

This method is not idempotent and may not work correctly in
sequence with KCC.run().

:return: a list of DSA DN strings.
zCN=NTDS Settings,r   r&   )r   r   r   r   rh   rn   r6   r~   extendr}   r   replace)rL   dsasr   r   s       r+   	list_dsasKCC.list_dsas	  s     	  " !OO**,DKK$(NN$9$9$;=$;S ../BBJ$;= > - =s   ''C
c                     U(       d  U R                   c   [        U[        5       X2S9U l         gg! [        R                   a&  nUR
                  u  pg[        SU< SU< 35      eSnAff = f)a  Load the database using an url, loadparm, and credentials

If force is False, the samdb won't be reloaded if it already
exists.

:param dburl: a database url.
:param lp: a loadparm object.
:param creds: a Credentials object.
:param force: a boolean indicating whether to overwrite.

N)urlsession_infocredentialslpzUnable to open sam database z : )rF   r
   r	   r   rZ   r[   r   )rL   dburlr<  credsforcee1numre   s           r+   
load_samdbKCC.load_samdb	  si     DJJ&-"u0>0@/4=
 '
 << -WW
 %s , - --s   0 A*!A%%A*c                    U=(       a    U R                   nU(       d  U R                  c  g/ n/ n/ n/ nU R                  R                  5        H  nUR	                  UR
                  5        UR                  5       (       a  UR	                  S5        OUR	                  S5        UR                  R                  5        Hb  n	U	R                  5       (       a  UR	                  S5        OUR	                  S5        UR	                  U	R                  UR
                  45        Md     M     [        XUU R                  U[        X0R                  SUUS9  g)zHelper function to plot and verify NTDSConnections

:param basename: an identifying string to use in filenames and logs.
:param verify_properties: properties to verify (default empty)
Nz#cc0000z#0000ccredblueT)	re  r`  ra  r"   rJ   rK   r_  edge_colorsvertex_colors)rJ   rK   r9   r~   r   r   r   r   r   r  r   rB   r   )
rL   basenamerk  rJ   ri  r  edge_coloursvertex_coloursr   r  s
             r+   plot_all_connectionsKCC.plot_all_connections	  s    #2t{{$++3	$$++-C.yy{{%%i0%%i0((//1'')) ''. ''/  #..#--!@A 2 . 	x\!.."35$3D3D $,%3	5r-   c                   ^ ^" T R                   c   [        SU< 35        T R                  XUSS9  U(       a  T R                   R                  SU-  5         T R	                  5         T R                  5         T R                  5         T R                  5         T R                  5         T R                  5         T R                  (       d  T R                  Gb  0 nT R                  R                  5        H3  m"UR                  S T"R                  R!                  5        5       5        M5     T R#                  S5        / n	T R$                  R'                  5       u  pU
R!                  5        H:  u  p[)        SU-  5        U	R+                  T R$                  R,                  U45        M<     [/        S	U	S
T R0                  S[(        T R                  T R                  S9  / n	T R                  R                  5        H  m"T"R                  R                  5        H  nUR'                  5       u  pU
R!                  5        H^  u  nnUR2                   HH  n[)        SU-  5        [5        UR6                  5      nUU   nU	R+                  UR,                  U45        MJ     M`     M     M     [/        SU	S
T R0                  S[(        T R                  T R                  S9  / n	/ nT R8                  R                  5        H  nSSKJn  UR>                  RA                  S5      nSU" U5      RC                  5       SS -   n[D        RF                  " URH                  S5       H0  u  nnU	R+                  US   US   45        UR+                  U5        M2     M     Sn[/        SU	ST R0                  U[(        T R                  T R                  US9	  U(       an  T RJ                  R                  R                  5        H5  n[M        U 4S jURN                  R!                  5        5       5      Ul'        M7     T R#                  S5        U(       a  T R                  R                  5        HW  m"T"R                  R                  5        H6  n[M        U U"4S jURN                  R!                  5        5       5      Ul'        M8     MY     T R#                  S5        U(       a  S nOSnT RQ                  U5        T RS                  5         T RU                  U5      nT RW                  U5        T RY                  5         T R[                  5         T R]                  5         T R                  (       d  T R                  Gb  T R#                  SS5        [^        R`                  " S[c        W5      -  5        / n	/ nT R$                  R,                  nT R$                  R'                  5       u  pUR!                  5        Hn  u  nn U R2                   HX  n[5        UR6                  5      n!U	R+                  UUU!   45        UR+                  S[5        U Rd                  5      SS -   5        MZ     Mp     [/        S U	S
T R0                  S[(        T R                  T R                  US9	  / n	T R                  R                  5        H  m"T"R                  R                  5        Hv  nUR'                  5       u  pUR                  5        HM  n U R2                   H:  n[5        UR6                  5      nUU   nU	R+                  UR,                  U45        M<     MO     Mx     M     [/        S!U	S
T R0                  S[(        T R                  T R                  S9  g!   e = f)"aZ  Perform a KCC run, possibly updating repsFrom topology

:param dburl: url of the database to work with.
:param lp: a loadparm object.
:param creds: a Credentials object.
:param forced_local_dsa: pretend to be on the DSA with this dn_str
:param forget_local_links: calculate as if no connections existed
       (boolean, default False)
:param forget_intersite_links: calculate with only intrasite connection
       (boolean, default False)
:param attempt_live_connections: attempt to connect to remote DSAs to
       determine link availability (boolean, default False)
:return: 1 on error, 0 otherwise
Nz"samdb is None; let's load it from F)r?  zCN=NTDS Settings,%sc              3   T   #    U  H  u  p[        UR                  5      U4v   M      g 7frs   rt   )rv   rf   r   s      r+   rx   KCC.run.<locals>.<genexpr>	  s+      )D,B .8U +.cll*;U)C,Bs   &(dsa_initialzc_rep %sdsa_repsFrom_initialTr/   r^  zrep %sdsa_repsFrom_initial_allr   )md5r   #r  r   r&   r  dsa_sitelink_initial)r_  r`  ra  r"   rJ   rK   rG  c              3      >#    U  HE  u  pUR                  5       (       d&  UR                  TR                  R                  ;  d  M@  X4v   MG     g 7frs   )r   r  rE   r}   )rv   kr  rL   s      r+   rx   rP  2
  sK      -G-F 9=010B0B0D0D./ll.2ll.D.D/E .4aV-Fs   ?A
Adsa_forgotten_localc              3   ~   >#    U  H2  u  pTTR                   L d  M  UR                  5       (       d  M-  X4v   M4     g 7frs   )rE   r   )rv   rX  r  rL   r   s      r+   rx   rP  <
  sB      1G1J =AA48DLL4H 28 231C1C1E 28!1Js   ==
=dsa_forgotten_allc                      [         R                  " XR                  U R                  5        g! [         R                   a     gf = f)NFT)r   drsuapi_connectr<  r>  drsException)rL   dnsnames     r+   r   KCC.run.<locals>.pingF
  s>    %!11'77DJJO   %11 %$%s   +. AA	dsa_finalzthere are %d dsa guidsdsa_repsFrom_finaldsa_repsFrom_final_all)3rF   r    rB  set_ntds_settings_dnr   r   r   r   rh   rn   rJ   rK   r6   r~   r|   r}   r-  rL  rC   r   r   r   r   r   rB   r   r\   r   r8   hashlibrT  rf   encode	hexdigestr   rd  	site_listrE   r  r   r   r0  r  r  rW  r   r  r"   ro  r   nc_guid)#rL   r=  r<  r>  forced_local_dsaforget_local_linksforget_intersite_linksattempt_live_connectionsguid_to_dnstrri  current_repsneeded_repsrf   rR  r   r   r  r   r(   dsa_dndot_colourslinkrT  tmp_strcolourr   r   ra  r   r  rG  my_dnstrr1  guid_strr   s#   `                                 @r+   runKCC.run	  sn   " ::uFGOOEuEO:JJ++,A,<-= >]	!$$&""$##%{{d//; " OO224D!(( )D,0NN,@,@,B)D D 5
 ))-8	,0KK,F,F,H)$0$6$6$8LE*u,-$$dkk&;&;U%CD %9 5y(,D4E4E*,E$++,0,=,=?
 	 OO224D#~~446474F4F4H1+7+=+=+?KFC-0-=-=	 %hn 5+.y/L/L+M)6x)@ ) 0 0#--1H I	 .> ,@  7 5 99(,D4E4E*,E$++,0,=,=?
 	  //668D+"jj//7G 3w<#9#9#;BQ#??F ) 6 6t~~q I1!((!A$!6#**62 !J	 9 ,
5y(-%)%6%6:%*4;;,0,=,=+68 "<<1188:C(, -G-0->->-D-D-F-G )GC% ; ))*?@% OO224D#~~446,0 1G141B1B1H1H1J1G -G)  7 5 ))*=>'  
 11$7 NN !NN40M ))-8 ##% 99; ''){{d//;))+*8: ##$<$'$6%7 8 	 ;;00,0KK,F,F,H)$/$5$5$7LE5%*%7%7	#&y'D'D#E!(((M(4K)LM#**3U]]1CBQ1G+GH &8 %8 3Y%)%6%6*,E$++,0,=,=+6	8 	 OO224D#~~446474F4F4H1%0%7%7%9E-2-?-?	+.y/L/L+M)6x)@ ) 0 0#--1H I .@ &:  7 5 7(,D4E4E*,E$++,0,=,=? 	s   \]' ']*c                      [         R                  " XUU5      U l        g! [         R                   a   n[        R
                  " U5         SnAgSnAff = f)a  Import relevant objects and attributes from an LDIF file.

The point of this function is to allow a programmer/debugger to
import an LDIF file with non-security relevant information that
was previously extracted from a DC database.  The LDIF file is used
to create a temporary abbreviated database.  The KCC algorithm can
then run against this abbreviated database for debug or test
verification that the topology generated is computationally the
same between different OSes and algorithms.

:param dburl: path to the temporary abbreviated db to create
:param lp: a loadparm object.
:param ldif_file: path to the ldif file to import
:param forced_local_dsa: perform KCC from this DSA's point of view
:return: zero on success, 1 on error
Nr&   r   )r   ldif_to_samdbrF   	LdifErrorr!   critical)rL   r=  r<  	ldif_filerj  r   s         r+   import_ldifKCC.import_ldif
  sM    "	+99%Y:JLDJ
  "++ 	OOA	s     AAAc                      [         R                  " U R                  XUU5        g! [         R                   a   n[        R
                  " U5         SnAgSnAff = f)a  Save KCC relevant details to an ldif file

The point of this function is to allow a programmer/debugger to
extract an LDIF file with non-security relevant information from
a DC database.  The LDIF file can then be used to "import" via
the import_ldif() function this file into a temporary abbreviated
database.  The KCC algorithm can then run against this abbreviated
database for debug or test verification that the topology generated
is computationally the same between different OSes and algorithms.

:param dburl: LDAP database URL to extract info from
:param lp: a loadparm object.
:param cred: a Credentials object.
:param ldif_file: output LDIF file name to create
:return: zero on success, 1 on error
Nr&   r   )r   samdb_to_ldif_filerF   r|  r!   r}  )rL   r=  r<  r>  r~  r   s         r+   export_ldifKCC.export_ldif
  sN    "	11$**e2;=
  "++ 	OOA	s   #& AAA)r"   rK   r9   r:   r=   r<   r7   r@   r>   rA   rC   rB   rE   rD   rH   r5   rI   rF   r6   r8   rG   rJ   )FFFNrs   )T)F)r/   )NFFF).__name__
__module____qualname____firstlineno____doc__rM   rh   rn   rz   r   r   r   r   r   r   r   r   r   r   r  r  r  r8  r?  rW  r[  r   rt  rn  r   r  r  r  r  r  r  r  r'  r0  r6  rB  rL  rx  r  r  __static_attributes__r/   r-   r+   r2   r2   N   s    FK"()T!GF2<%.	:$&8Ft,<2KhB8$-2-h74r/"&$M;^%Nz0~K2&P<Wr12fz*x0dz+x8t7v">H+ZD*LN$`0-,!5F 6:=B%*xt2r-   r2   )4r  r   	functoolsr   r   sambar   r   r   r   r   
samba.authr	   samba.samdbr
   samba.dcerpcr   r   samba.kcc.kcc_utilsr   r   r   r   r   r   r   r   r   r   r   samba.kcc.graphr   	samba.ndrr   samba.kcc.graph_utilsr   	samba.kccr   r   r   r   samba.kcc.debugr   r    r!   r"   samba.commonr#   r,   r0   objectr2   r/   r-   r+   <module>r     sn   ,      * & & %  & D D H H E E 9  0 ( @ " 3 3  A"t)& t)r-   