a
     {a2                    @   s  d dl mZ d dlmZ d dlmZ d dlmZmZm	Z	m
Z
mZ d dlZd dlZd dlZd dlmZmZ d dlmZmZmZmZmZmZmZmZ d dlmZ d d	lmZmZ d d
lm Z m!Z!m"Z"m#Z#m$Z$m%Z% d dl&m'Z' d dl(m)Z) d dlm*Z* d dl+m,Z, d dl-m.Z. d dlm/Z/ d dlm0Z0 d dl1m2Z2 d dlm3Z3m4Z4 d dlm5Z5 d dl6m7Z7m8Z8m9Z9 d dl:Z:d dl;Z;d dl<Z<d dl=Z=d dl>Z>d dl?Z?d dl@mAZA d dlBmCZC d dlBmDZD d dlEmFZF G dd deGZHG dd deIZJd*dd ZKd+d!d"ZLd,d$d%ZMG d&d' d'eJZNG d(d) d)eNZOdS )-    )print_function)system_session)SamDB)gensecLdb	drs_utilsarcfour_encryptstring_to_byte_arrayN)ndr_pack
ndr_unpack)securitydrsuapimiscnbtlsadrsblobs	dnsserverdnsp)DS_DOMAIN_FUNCTION_2003)CredentialsDONT_USE_KERBEROS)secretsdb_self_join	provisionprovision_fillFILL_DRSFILL_SUBDOMAINDEFAULTSITE)
setup_path)Schema)
descriptor)Net)setup_bind9_dns)read_and_sub_file)werror)	b64encode)WERRORErrorNTSTATUSError)sd_utils)ARecord
AAAARecordCNameRecord)OrderedDict)	text_type)
get_string)CommandErrorc                       s   e Zd Z fddZ  ZS )DCJoinExceptionc                    s   t t| d|  d S )NzCan't join, error: %s)superr/   __init__)selfmsg	__class__ ,/usr/lib/python3/dist-packages/samba/join.pyr1   ;   s    zDCJoinException.__init__)__name__
__module____qualname__r1   __classcell__r6   r6   r4   r7   r/   9   s   r/   c                   @   s:  e Zd ZdZdLddZdMddZdNdd	ZdOd
dZdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ ZdPd0d1Zd2d3 Zd4d5 Zd6d7 Zd8d9 Zd:d; Zd<d= Z d>d? Z!d@dA Z"dBdC Z#dDdE Z$dFdG Z%dHdI Z&dJdK Z'dS )QDCJoinContextzPerform a DC join.NFc              
   C   s  || _ || _|| _|| _|| _|
| _|| _|| _|| _|| _	d | _
g | _g | _| j| tjB  t| j| jd| _|| _|| _|r|| _| jj| _nj| jr|d u r| | j| _n.| j d|  | || _| j d| j  td| j t | j| jd| _| jd u rt| _z| jjtjg d W n: tj yd } z|j!\}}t"|W Y d }~n
d }~0 0 t#| j$ | _%t#| j& | _'t#| j( | _)t#| j* | _+t,-| j. | _/| j/| _0| 1 | _2| 3 | _4t56t#t78 | _9| j: | _;| < | _=| > | _?|	d ur|	| _@ntABdd| _@| jC | _D|r|| _Ed	| jE | _Fd
| jE| j| j+f | _Gd| jG | _Hd| jE| j%f | _Id| jEJ | jDf | _K| jL | _Md| j% }| N|rd| jE|f | _Ond | _Od| jE d| jK d| jK| jMf g| _P| jjtjdg| j%d}|d d d | _Qd| j% | _Rd| j' | _SdtT| jR }| jjtjUg | jV |d}|d u rtd| _Wn$tX|dkrd| _WtYd n|| _W| jD| _Zd | _[t\j]t\j^B t\j_B t\j`B t\jaB | _bd | _cd | _dd | _ed| _fd | _gd | _\d | _hd| _id | _jd | _kd | _ld | _md| _nd S )N)credslpz&Finding a writeable DC for domain '%s'zFound DC %s	ldap://%surlsession_infocredentialsr>   scopeattrs      %s$z"CN=%s,CN=Servers,CN=%s,CN=Sites,%szCN=NTDS Settings,%szCN=%s,OU=Domain Controllers,%s%s.%szGCN=Topology,CN=Domain System Volume,CN=DFSR-GlobalSettings,CN=System,%szCN=%s,%szHOST/%szGC/%s/%sZrIDManagerReference)rE   rF   baser   zDC=DomainDnsZones,%szDC=ForestDnsZones,%s$(&(objectClass=crossRef)(ncName=%s))rE   rF   rK   
expressionNONEzCNO DNS zone information found in source domain, not replicating DNSF)ologgerr=   r>   site	targetdir	use_ntvfsplaintext_secretsbackend_storebackend_store_sizepromote_existingpromote_from_dnnc_listfull_nc_listZset_gensec_featuresZget_gensec_featuresr   ZFEATURE_SEALr    netserverforced_local_samdbsamdbrA   find_dc_siteinfofind_dcr   r   r   searchldb
SCOPE_BASELdbErrorargsr/   strget_default_basednbase_dnget_root_basednroot_dnZget_schema_basedn	schema_dnZget_config_basedn	config_dnr   dom_sidZget_domain_siddomsid	forestsidget_domain_namedomain_nameget_forest_domain_nameforest_domain_namer   GUIDuuidZuuid4invocation_idZget_dsServiceName
dc_ntds_dnget_dnsHostNameZdc_dnsHostNameget_behavior_versionbehavior_version	acct_passsambaZ generate_random_machine_passwordZdomain_dns_name	dnsdomainmynamesamname	server_dnntds_dnacct_dnlowerdnshostnameZforest_dns_name	dnsforest	dn_existstopology_dnSPNsrid_manager_dndomaindns_zoneforestdns_zonebinary_encodeSCOPE_ONELEVELget_partitions_dndns_backendlenprintrealm	tmp_samdbr   ZDRSUAPI_DRS_INIT_SYNCZDRSUAPI_DRS_PER_SYNCZDRSUAPI_DRS_GET_ANCZDRSUAPI_DRS_GET_NC_SIZEZDRSUAPI_DRS_NEVER_SYNCEDreplica_flagsnever_reveal_sid
reveal_sidconnection_dnRODC	krbtgt_dn	managedby	subdomain	adminpasspartition_dndns_a_dndns_cname_dnforce_all_ips)ctxrP   r\   r=   r>   rQ   netbios_namerR   domainmachinepassrS   r   rW   rT   rU   rV   r]   eenumestrZtopology_baseZres_rid_managerexprZres_domaindnsr6   r6   r7   r1   B   s    











zDCJoinContext.__init__c                 C   s   |rNz| j j|tjdgd}W n ty2   Y d S 0 |D ]}| j|jdd q8z| j | td|  W n ty|   Y n0 d S )NdnrK   rE   rF   T	recursivez
Deleted %s)	r^   rb   rc   r   	Exceptiondel_noerrorr   deleter   )r   r   r   resrr6   r6   r7   r      s    zDCJoinContext.del_noerrorc                 C   s  | j j| j  dt| j ddgd}t|dkr8d S |st }|| j	 z:|
| j	 || j  td| j t || j	d}W n   Y nD0 |jtjdd	gd
}|d d	 d |d d d krtd| j | j|d jdd |d jddd}|d ur|| _| | j | j j| j  dtd| j td| j f g d}|rl| j|d jdd | j j| j  dtd| j  g d}|rtdtd| j td| j f d S )NsAMAccountName=%smsDS-krbTgtLink	objectSIDrK   rN   rF   r   r?   r@    tokenGroups)rE   rK   rF   zNot removing account %s which looks like a Samba DC account matching the password we already have.  To override, remove secrets.ldb and secrets.tdbTr   msDS-KrbTgtLink)idxz/(&(sAMAccountName=%s)(servicePrincipalName=%s))dns-%szdns/%sz(sAMAccountName=%s)znNot removing account %s which looks like a Samba DNS service account but does not have servicePrincipalName=%s)r^   rb   rh   rc   r   r   r   r   guessr>   Zset_machine_accountset_kerberos_stater=   Zget_kerberos_stater   r\   r   rd   r/   r   r   getnew_krbtgt_dnr   r   )r   forcer   r=   Zmachine_samdbZ	token_resr   r6   r6   r7   cleanup_old_accounts   sd    


z"DCJoinContext.cleanup_old_accountsc                 C   sT  | j s| j|d | jdur(| | j | jdur>| | j | | j | j| jdd | jrl| | j | jr~| | j | j r(d}t	
d| j|f | j| j}t	 }t	 |_|d|tj}t	 }| j|_|||t	j}|||jj t	 }| j|_|||t	j}|||jj | jr<| | j | jrP| | j dS )z$Remove any DNs from a previous join.)r   NTr   signncacn_ip_tcp:%s[%s]r   )r   r   r   r   r   r   r   r   r   r   lsarpcr\   r>   r=   ObjectAttributeQosInfosec_qosOpenPolicy2r   SEC_FLAG_MAXIMUM_ALLOWEDStringr   stringQueryTrustedDomainInfoByName!LSA_TRUSTED_DOMAIN_INFO_FULL_INFODeleteTrustedDomaininfo_exsidrt   r   r   )r   r   binding_optionslsaconn
objectAttr
pol_handlenamer`   r6   r6   r7   cleanup_old_join  sF    


zDCJoinContext.cleanup_old_joinc                 C   s   | j rtd| jj| j dt| j g dd}t|dkrPtd| j d|d v std|d v std	|d v rtd
| j t	|d d d t
jjt
jjB @ dkrtd| j |d j| _dS )z]confirm that the account is just a bare NT4 BDC or a member server, so can be safely promotedz Can not promote into a subdomainr   )r   userAccountControlserverReferenceBLrIDSetReferencesr   r   zcCould not find domain member account '%s' to promote to a DC, use 'samba-tool domain join' instead'r   r   r   zhAccount '%s' appears to be an active DC, use 'samba-tool domain join' if you must re-create this accountr   zZAccount %s is not a domain member or a bare NT4 BDC, use 'samba-tool domain join' instead'N)r   r   r^   rb   rh   rc   r   r   r   intr}   dsdbUF_WORKSTATION_TRUST_ACCOUNTUF_SERVER_TRUST_ACCOUNTr   rX   r   r   r6   r6   r7   promote_possibleK  s"    $zDCJoinContext.promote_possiblec              
   C   s   z$| j j|tjtjB tjB d| _W nV ty^ } z"td||j	d f W Y d}~n&d}~0  t
yz   td| Y n0 | jjdur| jjdkr| jj| _| jjS )z(find a writeable DC for the given domain)r   flagsz1Failed to find a writeable DC for domain '%s': %s   Nz-Failed to find a writeable DC for domain '%s'r   )r[   finddcr   NBT_SERVER_LDAPNBT_SERVER_DSZNBT_SERVER_WRITABLE	cldap_retr&   r.   rf   r   client_siterQ   Zpdc_dns_name)r   r   errorr6   r6   r7   ra   ^  s    $
zDCJoinContext.find_dcc                 C   s:   d }| j j|tjtjB d}|jd ur6|jdkr6|j}|S )N)Zaddressr   r   )r[   r   r   r   r   r   )r   r\   rQ   r   r6   r6   r7   r_   k  s    
zDCJoinContext.find_dc_sitec                 C   sD   | j j| jtjdgd}d|d v r8t|d d d S tjjS d S )NmsDS-Behavior-Versionr   r   )	r^   rb   ri   rc   rd   r   r}   r   ZDS_DOMAIN_FUNCTION_2000r   r6   r6   r7   rz   s  s    z"DCJoinContext.get_behavior_versionc                 C   s*   | j jdtjdgd}t|d d d S )Nr   dnsHostNamer   r   )r^   rb   rc   rd   rg   r   r6   r6   r7   ry   z  s    zDCJoinContext.get_dnsHostNamec              
   C   sJ   | j  }| j j|tjdgdtt| j   d}t|d d d S z9get netbios name of the domain from the partitions recordnETBIOSNamez	ncName=%s)rK   rE   rF   rN   r   )r^   r   rb   rc   r   r   rg   rh   r   Zpartitions_dnr   r6   r6   r7   rq   ~  s
    
zDCJoinContext.get_domain_namec              
   C   sJ   | j  }| j j|tjdgdtt| j   d}t|d d d S r   )r^   r   rb   rc   r   r   rg   rj   r   r6   r6   r7   rs     s
    
z$DCJoinContext.get_forest_domain_namec                 C   s:   | j j| jg dt| jtjtjj	f d}t
|d jS )7get the parent domain partition DN from parent DNS namez9(&(objectclass=crossRef)(dnsRoot=%s)(systemFlags:%s:=%u)))rK   rF   rN   r   )r^   rb   rm   rc   r   Zparent_dnsdomainZOID_COMPARATOR_ANDr}   r   SYSTEM_FLAG_CR_NTDS_DOMAINrg   r   r   r6   r6   r7   get_parent_partition_dn  s    

z%DCJoinContext.get_parent_partition_dnc              	   C   s   | j jd| j dgtjdgd}d|d vrBtd| j| j jf z4tt	
t| j |d d d dd}W n* ty   td	|d d d  Y n0 d
|| jf }|S )r   zCN=Partitions,%sZfSMORoleOwnerextended_dn:1:1)rK   rF   rE   controlsr   z1Can't find naming master on partition DN %s in %sutf8ru   3Can't find GUID in naming master on partition DN %s%s._msdcs.%s)r^   rb   rm   rc   rd   r/   r   rA   rg   r   ru   Dndecodeget_extended_componentKeyErrorr   )r   r   Zmaster_guidZmaster_hostr6   r6   r7   get_naming_master  s    4zDCJoinContext.get_naming_masterc                 C   s8   | j jdtjdgd}|d d d }t| j d|S )zhget the SID of the connected user. Only works with w2k8 and later,
           so only used for RODC joinr   r   r   r   r   )r^   rb   rc   rd   r-   schema_format_value)r   r   Zbinsidr6   r6   r7   	get_mysid  s    zDCJoinContext.get_mysidc              
   C   sh   z| j j|tjg d}W nJ tjyb } z0|j\}}|tjkrLW Y d}~dS  W Y d}~n
d}~0 0 dS )zcheck if a DN existsr   NFT)r^   rb   rc   rd   re   rf   ZERR_NO_SUCH_OBJECT)r   r   r   Ze5r   r   r6   r6   r7   r     s    

zDCJoinContext.dn_existsc                 C   s   t d| j  | jdttjjtjjB dd| j d}| j	|dg | jj
| jtjdgd}|d	 d d	 | _t d
| j  t }t| j| j|_t| jtjd|d< | j| d| j| jf | _t d| j| jf  | j| j| j dS )z#RODCs need a special krbtgt account	Adding %suserTRUEzkrbtgt for %s)r   objectclassZuseraccountcontrolZshowinadvancedviewonlyZdescriptionrodc_join:1:1samAccountNamer   r   zGot krbtgt_name=%sr   zCN=%s,CN=Users,%szRenaming %s to %sN)r   r   rg   r}   r   UF_NORMAL_ACCOUNTUF_ACCOUNTDISABLEr   r^   addrb   rc   rd   Zkrbtgt_nameMessager   r   r   MessageElementFLAG_MOD_REPLACEmodifyri   r   rename)r   recr   mr6   r6   r7   add_krbtgt_account  s,    z DCJoinContext.add_krbtgt_accountc                 C   sT   d}| j  dkr|d7 }d| j|f }t|| j | j| _t| j\| _| _dS )z.make a DRSUAPI connection to the naming masterseal	   ,printr   N)	r>   	log_levelr\   r   r=   r   Z
drs_DsBinddrsuapi_handleZbind_supported_extensions)r   r   Zbinding_stringr6   r6   r7   drsuapi_connect  s    zDCJoinContext.drsuapi_connectc              	   C   sB   t | j| jd| _tt dd| j| jddd| _| j	| j dS )z2create a temporary samdb object for schema queries)schemadnNF)rB   rA   Zauto_connectrC   r>   global_schemaZam_rodc)
r   ro   rl   Z
tmp_schemar   r   r=   r>   r   Z
set_schemar   r6   r6   r7   create_tmp_samdb  s    

zDCJoinContext.create_tmp_samdbc                 C   s    t  }| j||_d|_dS )z$build a DsReplicaAttributeCtr objectr   N)r   ZDsReplicaAttributer   Zget_attid_from_lDAPDisplayNameZattidZ	value_ctr)r   attrnameZ	attrvaluer   r6   r6   r7   build_DsReplicaAttribute  s    z&DCJoinContext.build_DsReplicaAttributec                 C   s>  | j du r|   | jdu r$|   g }|D ]}t  }|d |_g }|D ]Z}|dkrXqJt|| tsr|| g}n|| }dd |D }| j| j||}|	| qJt 
 }	t||	_||	_t  }
||
_|	|
_t  }|
|_|	| q,t  }|d |_|j}|dd D ]}||_|}q| j | jd|\}}|dkr|jt jkrftd|j  td	|jd tjkrtd
|j  td	|dkr8|jdkrtd|j |j j!d tjkr|j j"du rtd|j j!d   ntd
|j j!d |j j"jf  td	|j jt jkr8td|j j  td	|j#S )z,add a record via the DRSUAPI DsAddEntry callNr   c                 S   s$   g | ]}t |tr|d n|qS )r   )
isinstancer,   encode).0xr6   r6   r7   
<listcomp>      z,DCJoinContext.DsAddEntry.<locals>.<listcomp>r   r      z!DsAddEntry failed with dir_err %uzDsAddEntry failedz(DsAddEntry failed with status %s info %s   zexpected err_ver 1, got %uz.DsAddEntry failed with status %s, info omitted)$r   r  r   r  DsReplicaObjectIdentifierr   r  listZdsdb_DsReplicaAttributeappendZDsReplicaAttributeCtrr   Znum_attributesZ
attributesZDsReplicaObjectZ
identifierattribute_ctrZDsReplicaObjectListItemobjectZDsAddEntryRequest2Zfirst_objectZnext_object
DsAddEntryr  Zdir_errZDRSUAPI_DIRERR_OKr   RuntimeErrorZextended_errr#   ZWERR_SUCCESSZerr_verZerr_dataZstatusr`   objects)r   recsr(  r
  idrF   avZrattrr$  r%  Zlist_objectZreq2prevolevelZctrr6   r6   r7   r&    sn    






zDCJoinContext.DsAddEntryc                 C   s  t d| j  td| jfddttjjfd| jfg}| j| j	| jg}| j
tjjkrdttjj|d< | j
tjjkr|| j|d< | jrd| j |d	< | j|d
< d|d< nfd| j |d	< | j
tjjkr| j|d< g |d< |D ]}|| jv r|d | qd|d< t| j|d< |S )z return the ntdsdsa object to addr   r   )r   ZnTDSDSAsystemFlagsZdMDLocationr   zmsDS-HasDomainNCszCN=NTDS-DSA-RO,%sobjectCategoryzmsDS-HasFullReplicaNCsZ37optionszCN=NTDS-DSA,%szmsDS-HasMasterNCsZHasMasterNCs1invocationId)r   r   r+   rg   r}   r   #SYSTEM_FLAG_DISALLOW_MOVE_ON_DELETErl   ri   rm   r{   r   ZDS_DOMAIN_FUNCTION_2008_R2r   rZ   r#  r
   rw   )r   r
  rY   ncr6   r6   r7   join_ntdsdsa_obj,  s4    




zDCJoinContext.join_ntdsdsa_objc                 C   s   |   }| jr"| jj|dgd n$| jr:| j|dg n| |g | jj| jtj	dgd}t
| jd|d d d | _dS )zadd the ntdsdsa objectrelax:0r   r   Z
objectGUIDr   r   N)r7  r]   r^   r  r   r&  rb   r   rc   rd   r   ru   r   	ntds_guid)r   r
  r   r6   r6   r7   join_add_ntdsdsaW  s    zDCJoinContext.join_add_ntdsdsac                 C   s  | j rFtd| j   | j d| j| jt| jtjjB | jd}| j	tjj
kr^ttjj|d< n| jrlg |d< | jr~| j|d< n| jrg |d< | jr| j|d< n| jrg |d< | jr| j|d< n| jrg |d< |rt||d< | jr"| j| j kr| j| j| j  | jtj| j|tj n$d	}|d	ur6d
g}| jj||d | jrV|   | jrtd| j  | jdttjjtjjB tjjB | jd}| j r| j |d< | j| | j rd	| _!d	S | j"r| #  dt$| j% }| jj&tj'g | j( |d| j%f}dt$| j) }| jj&tj'g | j( |d| j)f}||fD ]n\}}|| j*vrZqBt+|dkrBt }	|d j,|	_,d}
| j-rd}
t.| j"tj/|
|	|
< | j|	 qB| j0d	urtd| j0  | j0ddd| j1d}| j| | j rtd| j   t }	t2| j| j |	_,t3t+| j4D ]$}| j4| 5dt| j!| j4|< q*t.| j4tjd|	d< | j|	 td| j  z(| jj6dt$| j | j7d| jd W nX tj8y  } z<|j9\}}|tj:krԂ | j;j<| j| j=| j7d  W Y d	}~n
d	}~0 0 | jj&| j tj>d!d"gd#}d!|d v rBt?|d d! d | _@nd	| _@tAtBjC|d d d | _Dtd$ t }	t2| j| j |	_,t.t| jtjd%|	d%< | j|	 | jEFd&rtGd'd(| _H| jItJtKd)| jL| jM| jNtO| jHPd*Qd+| jd,}|D ]\}}|tjRksJ |d- }td.|d-   |d/= |d0= ttjjStjjB |d%< z| j| W n@ tj8y } z$|j9\}}|tjTkr W Y d	}~n
d	}~0 0 qtd1| jN  z(| jj6d2t$| jN | jHd| jd W n\ tj8yB } z@|j9\}}|tj:kr | j;j<d3| jN | j=| jHd  W Y d	}~n
d	}~0 0 | jj&|tj>d!gd#}d!|d v rt?|d d! d | _Und	| _Ud	S )4z+add the various objects needed for the joinr   Zcomputer)r   ZobjectClassZdisplaynameZsamaccountnamer   r   zmsDS-SupportedEncryptionTypesr   zmsDS-NeverRevealGroupzmsDS-RevealOnDemandGroupZ	objectSidNr8  r9  r\   )r   r   r0  r   ZserverReferencerL   rM   r   r   zmsDS-NC-Replica-LocationszmsDS-NC-RO-Replica-LocationsZnTDSConnectionr   Z65)r   r   Zenabledconnectionr2  Z
fromServerzAdding SPNs to %sz	$NTDSGUIDZservicePrincipalNamezSetting account password for %sz((&(objectClass=user)(sAMAccountName=%s))F)Zforce_change_at_next_loginZusername)Zaccount_namerr   ZnewpasswordzmsDS-KeyVersionNumberr   r   zEnabling accountr   BIND9_rG   rH   zprovision_dns_add_samba.ldif	utf-16-ler   )Z	DNSDOMAINZDOMAINDNZHOSTNAMEZDNSPASS_B64ZDNSNAMEr   z#Adding DNS account %s with dns/ SPNclearTextPasswordZisCriticalSystemObjectz#Setting account password for dns-%sz,(&(objectClass=user)(samAccountName=dns-%s))r   )Vr   r   r   rg   r   r}   r   r  r   r{   ZDS_DOMAIN_FUNCTION_2008ZENC_ALL_TYPESrW   r   r   r   r
   rX   r^   r	  r  rc   r  Z	from_dictr  r  r   r  r   ZSYSTEM_FLAG_CONFIG_ALLOW_RENAMEZ%SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVEr5  r   r:  r   r;  r   r   rb   r   r   r   rY   r   r   r   r  ZFLAG_MOD_ADDr   rx   r   ranger   replaceZsetpasswordr|   re   rf   ZERR_UNWILLING_TO_PERFORMr[   set_passwordrr   rd   r   key_version_numberr   r   rn   new_dc_account_sidr   
startswithZgenerate_random_passworddnspassZ
parse_ldifr"   r   r~   ri   r   r$   r  r   ZCHANGETYPE_NONEr  ZERR_ENTRY_ALREADY_EXISTSdns_key_version_number)r   Zspecified_sidr
  r   r   r   Zforestpartzoner  attriZe2Znum_r   r)  Z
changetyper3   Zdns_acct_dnr   Ze3r6   r6   r7   join_add_objectsf  sz   




"








zDCJoinContext.join_add_objectsc              
   C   s  t d| j  ddt| jtjf i}tj| j|d}| jdd| j	 | j
| j| j| jttjjtjjB |d	}| jtjjkrt| j|d< |  }| ||g}t|d	krtd
|d j| _t d | jj| jtd| jtjtj d t d | jj| j!td| jtjtj d dS )zLadd the various objects needed for the join, for subdomains post replicationr   ZSubdomainAdminsz%s-%s)name_mapZcrossRefzCN=Cross-Ref,%s)	r   r   r1  nCNamer   ZdnsRootZtrustParentr0  ZntSecurityDescriptorr   r  z"Expected 2 objects from DsAddEntryr   zReplicating partition DN$00000000-0000-0000-0000-000000000000)exopr   zReplicating NTDS DNN)"r   r   rg   ro   r   ZDOMAIN_RID_ADMINSr   Z+get_paritions_crossref_subdomain_descriptorrp   rl   ri   rr   r~   Zparent_partition_dnr}   r   ZSYSTEM_FLAG_CR_NTDS_NCr   r{   r   r7  r&  r   r/   guidr:  repl	replicater   ru   r   ZDRSUAPI_EXOP_REPL_OBJDRSUAPI_DRS_WRIT_REPr   )r   rM  Z	sd_binaryr
  Zrec2r(  r6   r6   r7   join_add_objects2=  sD    

zDCJoinContext.join_add_objects2c                 C   s   t d | jj}t| jt || jt| j| j	| j
| j| j| j| j| j| j| jd| j| j| j| j| j| j| j| jdd}t d|j  |j| _|j| _|j| _|j| _| j| j_dS )Provision the local SAM.zCalling bare provision"active directory domain controllerT)smbconfrR   
samdb_fillr   rootdndomaindnr  configdnZserverdnr   Zhostname	domainsidr   
serverroleZsitenamer>   ZntdsguidrS   r   rT   rU   rV   Z
batch_modezProvision OK for domain DN %sN)r   r>   Z
configfiler   rP   r   rR   r   r   rk   ri   rl   rm   r   rr   r   ro   r|   rQ   r:  rS   r   rT   rU   rV   r[  r^   local_samdbpathsnamesrp   )r   rX  presultr6   r6   r7   join_provisionh  s,    
zDCJoinContext.join_provisionc                 C   s|  t d t| jjdgt | jjdd| _| jt| j	 | j| _| j
d | jj| jtjdgddgd	}d
|d vrtd| j| jjf z8ttt| j|d d d dd| j_W n* ty   td|d d d  Y n0 | j
d| jj  | j
d t| jjt | jd}t| j|| j
| j| jt| jt| j d| j| jj!| jj"| j#| j$d}t d| jj%  dS )rV  zReconnecting to local samdbz#transaction_index_cache_size:200000F)rA   r2  rB   r>   r  zFinding domain GUID from ncNameZncNamer   zreveal_internals:0)rK   rE   rF   r   rN  r   z2Can't find naming context on partition DN %s in %sr   ru   r   zGot domain GUID %szCalling own domain provisionrB   r>   rW  )
Zdom_for_fun_levelrR   rY  r   r^  r>   hostiphostip6r   r   zProvision OK for domain %sN)&r   r   r_  rA   r   r>   r^   set_invocation_idrg   rw   rP   r`   rb   r   rc   rd   r/   r   ru   r   r   r   ra  Z
domainguidr   r   r`  secretsr   r   rR   r   r|   re  rf  r   r   r~   )r   r   secrets_ldbrb  r6   r6   r7   join_provision_own_domain  s@    8z'DCJoinContext.join_provision_own_domainc                 C   s"   t d| j|f | j|| j| jS z2Creates a new DRS object for managing replicationsr   )r   Zdrs_Replicater\   r>   r_  rw   )r   
repl_credsr   r6   r6   r7   create_replicator  s    zDCJoinContext.create_replicatorc           
   
   C   s  t d | j  znt| j }| jdu rFt d ttj	}n| j}| j
rt }|| j |t || j || j n| j}d}| j dkr|d7 }| ||}|j| j||d| j
| jd |j| j||| j
| jd	 | js\| jtj@ sBt d
 |  jtjO  _|j| j||| j
| jd	 |  jtjN  _|j| j||| j
| jd	 t d | j| j fD ]:}|| j!v rpt dt"|  |j|||| j
| jd	 qp| j
r|j| j#||tj$dd |j| j%||tj$dd n| j&durfz|j| j&||tj'd W nX t(j)yd } z<|j*\}}	|tj+krNt d| j,  t d n W Y d}~n
d}~0 0 || _-|| _.|| _/t d W n   | j0   Y n0 | j1  | 2  dS )zReplicate the SAM.zStarting replicationNzUsing DS_BIND_GUID_W2K3r  r  r  T)Zschemarodcr   )rn  r   z;Replicating critical objects from the base DN of the domainz5Done with always replicated NC (base, config, schema)zReplicating %s)rP  rn  )rP  zdWARNING: Unable to replicate own RID Set, as server %s (the server we joined) is not the RID Master.zxNOTE: This is normal and expected, Samba will be able to create users after it contacts the RID Master at first startup.zCommitting SAM database)3r   r_  Ztransaction_startr   ru   r^   Zget_invocation_idr:  r   ZDRSUAPI_DS_BIND_GUID_W2K3r   r   r   r>   r   r   Zset_usernamer   rA  r|   r=   r  rm  rS  rl   r   rm   r   domain_replica_flagsDRSUAPI_DRS_CRITICAL_ONLYri   r   r   rY   rg   r   ZDRSUAPI_EXOP_REPL_SECRETr   r   ZDRSUAPI_EXOP_FSMO_RID_ALLOCr}   ZDsExtendedErrorrf   ZDRSUAPI_EXOP_ERR_FSMO_NOT_OWNERr\   rR  source_dsa_invocation_iddestination_dsa_guidZtransaction_cancelZtransaction_commitrefresh_ldb_connection)
r   rq  rr  rl  r   rR  r6  Ze1r   r   r6   r6   r7   join_replicate  s    















zDCJoinContext.join_replicatec              
   C   s   z| j jtjg d W n~ tjy } zd|j\}}|tjkrxd|v sLd|v rx| jd t	d| j
 t | j| jd| _ nt|W Y d }~n
d }~0 0 d S )NrD   Z!NT_STATUS_CONNECTION_DISCONNECTEDZNT_STATUS_CONNECTION_RESETz)LDB connection disconnected. Reconnectingr?   r@   )r^   rb   rc   rd   re   rf   ZERR_OPERATIONS_ERRORrP   Zwarningr   r\   r   r=   r>   r/   )r   r   r   r   r6   r6   r7   rs    s    



z$DCJoinContext.refresh_ldb_connectionc                 C   s   t  }t  |_t||j_td|j_t	
d|j_| j|_dt| j| jf |_t jt jB |_| js|| jt jO  _| j d u r|   | j | jd| d S )NrO  zS-0-0r   r   )r   ZDsReplicaUpdateRefsRequest1r!  Znaming_contextrg   r   r   ru   rQ  r   rn   r   r:  Zdest_dsa_guidr   Zdest_dsa_dns_nameZDRSUAPI_DRS_ADD_REFZDRSUAPI_DRS_DEL_REFr2  r   rT  r  ZDsReplicaUpdateRefsr  )r   r   r   r6   r6   r7   send_DsReplicaUpdateRefs(  s    

z&DCJoinContext.send_DsReplicaUpdateRefsc                 C   sN  t j}t jt jB }| j}d| j }| j}t| j}d||f }t	
| j| j}| jdt|||f  d}	t  d| j|	f | j| j}
d}t| j}t }| j|_tdt| jtjf |_z(|
|d| j||d	tj|d	d	
\}}W n< t y( } z"|j!d t"j#krd
}W Y d	}~n
d	}~0 0 |r|j$D ]}|j%D ]}|j&tj'ks`|j&tj(kr@t ) }||_$z|
*|d| j||d	| W n< t y } z"|j!d t"j#krn W Y d	}~n
d	}~0 0 q@q6|D ]z}|+ddkr| jd|||f  t,|}n| jd|||f  t-|}t ) }||_$|
*|d| j|||d	 qt|dkr>t./| j| j0}| jj1d||f |d\| _2}|j3| j2|dtj4tj5B  gd | jd|||f  t ) }t6|}||_$|
*|d| j|||d	 t./| j| j7}| jj1d||f |d\| _8}|j3| j8|dtj4tj5B  gd | jd d	S )a  Remotely Add a DNS record to the target DC.  We assume that if we
           replicate DNS that the server holds the DNS roles and can accept
           updates.

           This avoids issues getting replication going after the DC
           first starts as the rest of the domain does not have to
           wait for samba_dnsupdate to run successfully.

           Specifically, we add the records implied by the DsReplicaUpdateRefs
           call above.

           We do not just run samba_dnsupdate as we want to strictly
           operate against the DC we just joined:
            - We do not want to query another DNS server
            - We do not want to obtain a Kerberos ticket
              (as the KDC we select may not be the DC we just joined,
              and so may not be in sync with the password we just set)
            - We do not wish to set the _ldap records until we have started
            - We do not wish to use NTLM (the --use-samba-tool mode forces
              NTLM)

        z	_msdcs.%srJ   z&Adding %d remote DNS records for %s.%sr   r   Tz%s-%dr   NF:z,Adding DNS AAAA record %s.%s for IPv6 IP: %sz)Adding DNS A record %s.%s for IPv4 IP: %s)Zdns_partitionzsd_flags:1:%dr9  z$Adding DNS CNAME record %s.%s for %sz_All other DNS records (like _ldap SRV records) will be created samba_dnsupdate on first startup)9r   ZDNS_CLIENT_VERSION_LONGHORNZDNS_RPC_VIEW_AUTHORITY_DATAZDNS_RPC_VIEW_NO_CHILDRENr~   r   r   rg   r:  r}   Zinterface_ipsr>   r   rP   r`   r   r\   r=   r'   ZSDUtilsr^   r   r   rC  Z	owner_sidrn   ro   ZDOMAIN_RID_DCSZ	group_sidZDnssrvEnumRecords2r   ZDNS_TYPE_ALLr%   rf   r#   Z"WERR_DNS_ERROR_NAME_DOES_NOT_EXISTr
  ZrecordsZwTypeZ
DNS_TYPE_AZDNS_TYPE_AAAAZDNS_RPC_RECORD_BUFZDnssrvUpdateRecord2findr)   r(   rc   r   r   Z
dns_lookupr   Zmodify_sd_on_dnZSECINFO_OWNERZSECINFO_GROUPr*   r   r   )r   Zclient_versionZselect_flagsrH  Z
msdcs_zoner   Zmsdcs_cnameZcname_targetZIPsr   Zdns_connZ
name_foundZ	sd_helperZchange_owner_sdZbuflenr   r   r
  recordZdel_rec_bufZIPZadd_rec_bufZdomaindns_zone_dnZldap_recordZforestdns_zone_dnr6   r6   r7   join_add_dns_records9  s    





 


z"DCJoinContext.join_add_dns_recordsc              	   C   sT   | j | jfD ]B}|| jv r| jdt|  | jj|| j| j	| j
| jdd qd S )Nz!Replicating new DNS records in %sF)rn  r   Z	full_sync)r   r   rY   rP   r`   rg   rR  rS  rq  r:  r   r   )r   r6  r6   r6   r7   join_replicate_new_dns_records  s    
z,DCJoinContext.join_replicate_new_dns_recordsc                 C   s  | j d | jD ]}| | q| jrtd | jt| j	 | j
d| j t }t| jd| j |_tt| j	tjd|d< | j| | j|jdd | j d t }t| jd|_td	tjd
|d
< | j}tdt| tjd|d< | j| | jrdS t| jjt | jd}| j d t|| j| j| j | j!| j"| j#| j$| j%d	 | j&'drt(| j|| j)| j| j| j | j&| j*| j| j+| j,d dS )z=Finalise the join, mark us synchronised and setup secrets db.z=Sending DsReplicaUpdateRefs for all the replicated partitionszSetting RODC invocationIdZdomainFunctionalityz%sr4  r   (Setting isSynchronized and dsServiceName@ROOTDSEr   isSynchronized	<GUID=%s>dsServiceNameNrd  zSetting up secrets database)r   r   r~   Znetbiosnamer]  r   secure_channel_typerB  r<  )r   rE  Zos_levelrR   rB  )-rP   r`   rY   ru  r   r   r_  rg  rg   rw   Zset_opaque_integerr{   rc   r  r   r   r   r  r
   r  r  Z"set_attribute_replmetadata_versionr:  r   r   r`  rh  r   r>   r   rr   r   r~   r   ro   r|   r  rB  r   rD  r!   ra  rE  rR   rF  )r   r6  r  rQ  ri  r6   r6   r7   join_finalise  sd    	

	zDCJoinContext.join_finalisec                 C   s  t d| j  d}td| j|f | j| j}t }t |_|	d
d|tj}t }| j|j_| j|j_| j|_tjtjB |_tj|_tj|_zJt }| j|_|||tj}t d| j|jjf  |||jj W n t y   Y n0 t!| j"#d}t$% }	t&||	_'||	_(t$) }
t*+t,t-- |
_.tj/|
_0|	|
_1t$2 }d|_3|
g|_4t$5 }d|_3||_6t$7 }dgd	 }t8d	D ]}t9:d
d||< q||_;||_<||_=t>|}t?|j@|}tA }t&||_'t!||_BtC }||_D|E|||tjF}d| jG| jHf dtI|jtI|jtI|j| jJ| jGt>|t>|t>| jKd
}| jLM| d| jJ| jHf dtIt*jNjO| j"#dd| jJ d}| jLM| dS )zprovision the local SAM.z"Setup domain trusts with server %sr   zncacn_np:%s[%s]zutf-8z)Removing old trust record for %s (SID %s)r=  r   r   i   r   rH   zcn=%s,cn=system,%sZtrustedDomain)
r   r   Z	trustTypeZtrustAttributesZtrustDirectionZflatnameZtrustPartnerZtrustAuthIncomingZtrustAuthOutgoingZsecurityIdentifierzcn=%s$,cn=users,%sr   rI   )r   r   r   r>  r  N)Pr   r\   r   r   r>   r=   r   r   r   r   r   r   r   ZTrustDomainInfoInfoExr~   rr   r   r   ro   r   ZLSA_TRUST_DIRECTION_INBOUNDZLSA_TRUST_DIRECTION_OUTBOUNDZtrust_directionZLSA_TRUST_TYPE_UPLEVELZ
trust_typeZ!LSA_TRUST_ATTRIBUTE_WITHIN_FORESTZtrust_attributesr   r   r   r   r   r'  r	   Ztrustdom_passr  r   ZAuthInfoClearr   sizeZpasswordZAuthenticationInformationr}   Zunix2nttimer   timeZLastUpdateTimeZTRUST_AUTH_TYPE_CLEARZAuthTypeZAuthInfoZAuthenticationInformationArraycountZarrayZtrustAuthInOutBlobZcurrentZtrustDomainPasswordsr?  randomZrandint
confounderoutgoingZincomingr
   r   Zsession_keyZ	DATA_BUF2dataZTrustDomainInfoAuthInfoInternal	auth_blobZCreateTrustedDomainEx2ZSEC_STD_DELETEr   ri   rg   rt   rp   r_  r  r   ZUF_INTERDOMAIN_TRUST_ACCOUNT)r   r   r   r   r   r`   ZoldnameZoldinfoZpassword_blobZclear_valueZ clear_authentication_informationZ authentication_information_arrayr  Z	trustpassr  rJ  Ztrustpass_blobZencrypted_trustpassr  Z	auth_infoZtrustdom_handler
  r6   r6   r7   join_setup_trusts$  s    








zDCJoinContext.join_setup_trustsc                 C   s   | j | jg| _| j| j | jg| _| jrD| jdkrD|  j| jg7  _nj| js|  j| jg7  _| jdkr|  j| jg7  _|  j| jg7  _|  j| jg7  _|  j| jg7  _d S )NrO   )	rm   rl   rY   ri   rZ   r   r   r   r   r  r6   r6   r7   build_nc_lists  s    
zDCJoinContext.build_nc_listsc                 C   s   |    | jr|   n|   z\|   |   |   | jrX|   | 	  | 
  | jdkrr|   |   |   W n>   ztd W n ty   Y n0 |   |    Y n0 d S )NrO   zJoin failed - cleaning up)r  rW   r   r   rL  rc  rt  r   rU  rj  r  r   rz  r{  r  r   IOErrorrs  r  r6   r6   r7   do_join  s0    

zDCJoinContext.do_join)NNNNNNNNNFNFFNNN)F)F)F)N)(r8   r9   r:   __doc__r1   r   r   r   r   ra   r_   rz   ry   rq   rs   r   r   r   r   r  r  r  r  r&  r7  r;  rL  rU  rc  rj  rm  rt  rs  ru  rz  r{  r  r  r  r  r6   r6   r6   r7   r<   ?   s^          
 

5
/		C+
 X+-^ 	Her<   Fc                 C   sv  t | ||||||||	|
|||||d}|d|j | d|j  |d|j | d|j  d|j|jf |_d|jt	j
f dt	j dt	j dt	j dt	j g|_d|jt	jf |_| }d| }||_tjjtjjB tjjB |_|jd	|j d	|j g d
|j |_tj |_!d|_"| j#t$j%t$j&B O  _#|j#|_'|rT| j't$j(O  _'|)  | d|j|jf  dS )zJoin as a RODC.rU   rV   	workgroupworkgroup is %sr   realm is %szCN=krbtgt_%s,CN=Users,%sz<SID=%s-%s>z<SID=%s>zRestrictedKrbHost/%szCN=RODC Connection (FRS),%sTz$Joined domain %s (SID %s) as an RODCN)*r<   setrr   r`   r   r   ri   r   ro   r   ZDOMAIN_RID_RODC_DENYZSID_BUILTIN_ADMINISTRATORSZSID_BUILTIN_SERVER_OPERATORSZSID_BUILTIN_BACKUP_OPERATORSZSID_BUILTIN_ACCOUNT_OPERATORSr   ZDOMAIN_RID_RODC_ALLOWr   r   r   r}   r   r   Z)UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATIONZUF_PARTIAL_SECRETS_ACCOUNTr   r   extendr   r   r   r   ZSEC_CHAN_RODCr  r   r   r   %DRSUAPI_DRS_SPECIAL_SECRET_PROCESSINGZ$DRSUAPI_DRS_GET_ALL_GROUP_MEMBERSHIPro  rp  r  )rP   r\   r=   r>   rQ   r   rR   r   domain_critical_onlyr   rS   r   rW   rT   rU   rV   r   ZmysidZadmin_dnr6   r6   r7   	join_RODC  sP    

r  c                 C   s   t | ||||||||	|
|||||d}|d|j | d|j  |d|j | d|j  tjjtjjB |_	|j
d|j  tj|_| jtjtjB O  _|j|_|r| jtjO  _|  | d|j|jf  dS )	zJoin as a DC.r  r  r  r   r  z1E3514235-4B06-11D1-AB04-00C04FC2DCD2/$NTDSGUID/%sz!Joined domain %s (SID %s) as a DCN)r<   r  rr   r`   r   r}   r   r   ZUF_TRUSTED_FOR_DELEGATIONr   r   r#  r~   r   ZSEC_CHAN_BDCr  r   r   rT  !DRSUAPI_DRS_FULL_SYNC_IN_PROGRESSro  rp  r  ro   )rP   r\   r=   r>   rQ   r   rR   r   r  r   rS   r   rW   rT   rU   rV   r   r6   r6   r7   join_DC  s*    

r  rO   c
                 C   sz   t | |||||||||	d
}
|d|
j | d|
j  |d|
j | d|
j  |
  | d|
j|
jf  |
S )z%Creates a local clone of a remote DC.)rR   r   r   include_secretsrU   rV   r  r  r   r  zCloned domain %s (SID %s))DCCloneContextr  rr   r`   r   r  ro   )rP   r\   r=   r>   rR   r   r  r   rU   rV   r   r6   r6   r7   
join_clone  s    r  c                
       s2   e Zd ZdZd
 fdd	Zdd Zdd	 Z  ZS )r  zClones a remote DC.NFc                    s   t t| j||||||||	|
d	 d | _d | _d | _| jdd | _d | _	d | _
| j | _|  jtjtjB O  _|s|  jtjO  _| j| _d S )N)rR   r   r   rU   rV   .r   )r0   r  r1   r   r   r   r\   splitr   r:  r   r^   Zget_ntds_GUIDremote_dc_ntds_guidr   r   rT  r  r  ro  )r   rP   r\   r=   r>   rR   r   r   r  rU   rV   r4   r6   r7   r1   4  s&    
zDCCloneContext.__init__c                 C   sj   | j d t }t| jd|_tdtjd|d< | j	}tdt
| tjd|d< | j| d S )Nr|  r}  r   r~  r  r  )rP   r`   rc   r  r   r_  r   r  r  r  rg   r  )r   r  rQ  r6   r6   r7   r  O  s    
zDCCloneContext.join_finalisec                 C   s$   |    |   |   |   d S )N)r  rc  rt  r  r  r6   r6   r7   r  ]  s    zDCCloneContext.do_join)
NNNNNNNFNN)r8   r9   r:   r  r1   r  r  r;   r6   r6   r4   r7   r  1  s       r  c                	       sB   e Zd ZdZd fdd	Zdd Zdd	 Zd
d Zdd Z  Z	S )DCCloneAndRenameContextz6Clones a remote DC, renaming the domain along the way.NTc                    s8   t t| j||||||	|
||d	 || _|| _|| _d S )N)rR   r   r   r  rU   )r0   r  r1   new_base_dnnew_domain_name	new_realm)r   r  r  r  rP   r\   r=   r>   rR   r   r   r  rU   r4   r6   r7   r1   l  s    z DCCloneAndRenameContext.__init__c              	   C   s.   d| j |f }t|| j|| j| j| j| jS rk  )r\   r   Zdrs_ReplicateRenamerr>   r_  rw   ri   r  )r   rl  r   Zbinding_strr6   r6   r7   rm  z  s    z)DCCloneAndRenameContext.create_replicatorc                 C   s4   t  \}}|d| tjj|d}t| |S )z?Creates a non-global LoadParm based on the global LP's settingsF)Zfilename_for_non_global_lp)tempfileZmkstempdumpr}   ZparamZLoadParmosremove)r   Z	global_lpfdZtmp_fileZlocal_lpr6   r6   r7   create_non_global_lp  s
    	
z,DCCloneAndRenameContext.create_non_global_lpc                 C   s   | j }td| | j|S )z/Uses string substitution to replace the base DNrI   )ri   resubr  )r   Zdn_strZold_base_dnr6   r6   r7   	rename_dn  s    z!DCCloneAndRenameContext.rename_dnc                 C   s   t d | | j}t| jt | jt| j|| 	| j
| j| 	| j| 	| j| j| jd| j| jd}t d|j  |j| _|j| _dS )z"Provision the local (renamed) SAM.z(Provisioning the new (renamed) domain...rW  )rR   rY  r   r>   rZ  r[  r  r\  r   r]  r^  r   rU   z%Provision OK for renamed domain DN %sN)r   r  r>   r   rP   r   rR   r   r  r  rk   r  rl   rm   r  ro   r   rU   r[  r^   r_  r`  )r   Znon_global_lprb  r6   r6   r7   rc    s     



z&DCCloneAndRenameContext.join_provision)	NNNNNNNTN)
r8   r9   r:   r  r1   rm  r  r  rc  r;   r6   r6   r4   r7   r  i  s      
r  )NNNNNNNNFNFNFFNN)NNNNNNNNFNFNFFNN)
NNNNNNFrO   NN)PZ
__future__r   Z
samba.authr   Zsamba.samdbr   r}   r   r   r   r   r	   rc   rv   Z	samba.ndrr
   r   Zsamba.dcerpcr   r   r   r   r   r   r   r   Z
samba.dsdbr   Zsamba.credentialsr   r   Zsamba.provisionr   r   r   r   r   r   Zsamba.provision.commonr   Zsamba.schemar   r   Z	samba.netr    Zsamba.provision.sambadnsr!   r"   r#   base64r$   r%   r&   r'   Zsamba.dnsserverr(   r)   r*   Zloggingr  r  r  r  r  collectionsr+   Zsamba.compatr,   r-   Zsamba.netcmdr.   r   r/   r%  r<   r  r  r  r  r  r6   r6   r6   r7   <module>   s   (                  
8      
"    
8