a
    WaS                 ^   @   s  d dl mZmZ 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	Z	d dl
mZmZ d dl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Zd dlmZ d d	lmZ d d
l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'Z'd dl(m)Z)m*Z*m+Z+ d dl,m-Z- d dl.m/Z/m0Z0m1Z1m2Z2 d dl3m4Z4 d dl5m6Z6 d dl5m7Z7 d dl8m9Z9 d dl:m;Z; d dl<Z<dZ=dZ>dZ?dZ@dddddddddd	ZAdddddddddZBh dZCdZDdeD ZEd ZFd ZGe;eHd!ZId"d# ZJd$d% ZKd&d' ZLG d(d) d)eMZNG d*d+ d+eOZPd,d- ZQd.d/ ZRG d0d1 d1eOZSG d2d3 d3eOZTG d4d5 d5eOZUG d6d7 d7eUZVdd9d:ZWd;d< ZXd=d> ZYd?d@ ZZG dAdB dBeOZ[ddDdEZ\dFdGdGdGdGdGdFdGdGdGdGdGdFdFdGdFdHZ]dIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddedfdOdgdPdhdidjdkdldmdndodYdZdpdqdrdsdtdudvdwdxdydzd{d|d}d~dddddddddddddddddddddddddddddd}dddddd]Z^dd Z_dd Z`dddZadddZbdddZcdd Zddd Zedd ZfeddZgdd ZhdddZidd Zjdd Zkdd ZldddÄZmddń ZndddǄZodddɄZpdd˄ Zqdd̈́ Zrddτ ZsdddфZtG ddӄ deOZuddՄ Zvddׄ Zwddل Zxddۄ Zydd݄ Zzdd߄ Z{dS )    )print_functiondivisionN)ECHILDESRCH)OrderedDictCounterdefaultdict
namedtuple)query)traffic_packets)SamDB)LdbError)ClientConnection)securitydrsuapilsa)netlogon)netr_Authenticator)srvsvc)samr)
drs_DsBind)CredentialsDONT_USE_KERBEROSMUST_USE_KERBEROS)system_session)UF_NORMAL_ACCOUNTUF_SERVER_TRUST_ACCOUNTUF_TRUSTED_FOR_DELEGATIONUF_WORKSTATION_TRUST_ACCOUNT)SEC_CHAN_BDC)gensec)sd_utils)
get_string)get_samba_logger   ga2U0*3?-      ?)	dns0smbZ0x72ldapr)   r-   3r-   2cldapr/   dcerpc11r5   14nbnsr)   )r(   1r-   r<   r-   4r-   5r3   rA   r5   12r5   13r5   15>   browserr+   smb_netlogonsmb2g      $@)inamec                 G   s6   | t kr2|st|tjd nt|t| tjd dS )a  Print a formatted debug message to standard error.


    :param level: The debug level, message will be printed if it is <= the
                  currently set debug level. The debug level can be set with
                  the -d option.
    :param msg:   The message to be logged, can contain C-Style format
                  specifiers
    :param args:  The parameters required by the format specifiers
    fileN)DEBUG_LEVELprintsysstderrtuple)levelmsgargs rY   7/usr/lib/python3/dist-packages/samba/emulate/traffic.pydebugf   s    r[   c                  G   sf   t jdd}td|d d |d d f dtjd | D ]}t|tjd q8ttjd tj  d	S )
zK Print an unformatted log message to stderr, contaning the line number
    r$   )limitz %s:[01;33m%s [00mr       )endrP   rO   N)	tracebackextract_stackrR   rS   rT   flush)rX   tbarY   rY   rZ   debug_linenox   s    re   c                    sP   | rDd}| D ]}|d7 }||9 }|d; }qdd|    fdd}ndd }|S )zReturn a function that prints a coloured line to stderr. The colour
    of the line depends on a sort of hash of the integer arguments.      z
[38;5;%dm   c                     s,   t dkr(| D ]}td |f tjd qd S )Nr   z	%s%s[00mrO   rQ   rR   rS   rT   rX   rd   prefixrY   rZ   p   s    zrandom_colour_print.<locals>.pc                  W   s$   t dkr | D ]}t|tjd qd S )Nr   rO   ri   rj   rY   rY   rZ   rm      s    rY   )Zseedssxrm   rY   rk   rZ   random_colour_print   s    
rp   c                   @   s   e Zd ZdS )FakePacketErrorN)__name__
__module____qualname__rY   rY   rY   rZ   rq      s   rq   c                   @   st   e Zd ZdZdZdd Zedd Zd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dZdS )PacketzDetails of a network packet
	timestampip_protocolstream_numbersrcdestprotocolopcodedescextra	endpointsc
           
      C   sd   || _ || _|| _|| _|| _|| _|| _|| _|	| _| j| jk rR| j| jf| _	n| j| jf| _	d S Nrv   )
selfrw   rx   ry   rz   r{   r|   r}   r~   r   rY   rY   rZ   __init__   s    zPacket.__init__c              
   C   sh   | dd}|d d \}}}}}}}	}
|dd  }t|}t|}t|}| |||||||	|
|	S )N
	   )rstripsplitfloatint)clslinefieldsrw   rx   ry   rz   r{   r|   r}   r~   r   rY   rY   rZ   	from_line   s"    
zPacket.from_line        c                 C   sF   d | j}| j| }|d|| j| jp(d| j| j| j| j| j	|f	 fS )z5Format the packet as a traffic_summary line.
        r   z%f	%s	%s	%d	%d	%s	%s	%s	%s )
joinr   rw   rx   ry   rz   r{   r|   r}   r~   )r   Ztime_offsetr   trY   rY   rZ   
as_summary   s    
zPacket.as_summaryc                 C   sH   d| j | j| j| jpd| j| j| j| j| jr@dd	| j d ndf	 S )Nz:%.3f: %d -> %d; ip %s; strm %s; prot %s; op %s; desc %s %sr%      «r^      »r   )
rw   rz   r{   rx   ry   r|   r}   r~   r   r   r   rY   rY   rZ   __str__   s    zPacket.__str__c                 C   s   d|  S )Nz<Packet @%s>rY   r   rY   rY   rZ   __repr__   s    zPacket.__repr__c                 C   s,   |  | j| j| j| j| j| j| j| j| j		S r   )
	__class__rw   rx   ry   rz   r{   r|   r}   r~   r   r   rY   rY   rZ   copy   s    zPacket.copyc                 C   s   d| j | jf }|S )Nz%s:%sr|   r}   )r   r   rY   rY   rZ   as_packet_type   s    zPacket.as_packet_typec                 C   s2   | j | jf}|tv rt| S |tv r.t|  S dS )zA positive number means we think it is a client; a negative number
        means we think it is a server. Zero means no idea. range: -1 to 1.
        r   )r|   r}   CLIENT_CLUESSERVER_CLUES)r   keyrY   rY   rZ   client_score   s    
zPacket.client_scorec           	      C   s  d| j | jf }ztt|}W n> ty\ } z&td|j|f tjd W Y d}~dS d}~0 0 | j dkr|t	dd|j|f  t

 }z<|| ||rt

 }|| }td||j| j | j|f  W nT ty } z:t

 }|| }td	||j| j | j||f  W Y d}~n
d}~0 0 dS )
zSend the packet over the network, if required.

        Some packets are ignored, i.e. for  protocols not handled,
        server response messages, or messages that are generated by the
        protocol layer associated with other packets.
        packet_%s_%sz#Conversation(%s) Missing handler %srO   Nkerberosr$   z#Conversation(%s) Calling handler %sz%f	%s	%s	%s	%f	True	z%f	%s	%s	%s	%f	False	%s)r|   r}   getattrr   AttributeErrorrR   conversation_idrS   rT   r[   time	Exception)	r   conversationcontextfn_namefnestartr_   durationrY   rY   rZ   play  s@    



zPacket.playc                 C   s   | j |j  S r   rw   r   otherrY   rY   rZ   __cmp__,  s    zPacket.__cmp__Nc                 C   s   t | j| jS r   )is_a_real_packetr|   r}   )r   Zmissing_packet_statsrY   rY   rZ   is_really_a_packet/  s    zPacket.is_really_a_packet)r   )N)rr   rs   rt   __doc__	__slots__r   classmethodr   r   r   r   r   r   r   r   r   r   rY   rY   rY   rZ   ru      s   


(ru   c                 C   sj   | t v rdS | dkr |dkr dS d| |f }tt|d}|du rXtjd| tjd dS |tju rfdS dS )	zdIs the packet one that can be ignored?

    If so removing it will have no effect on the replay
    Fr-   r   r   Nzmissing packet %srO   T)SKIPPED_PROTOCOLSr   r   LOGGERr[   rS   rT   Znull_packet)r|   r}   r   r   rY   rY   rZ   r   3  s    
r   c                 C   s&   | dkrdS | |fdv rdS t | |S )zReturn true if a packet generates traffic in its own right. Some of
    these will generate traffic in certain contexts (e.g. ldap unbind
    after a bind) but not if the conversation consists only of these packets.
    waitF)r   r   r0   rG   r5   16)r   r   rY   rY   rZ   is_a_traffic_generating_packetI  s
    r   c                   @   s   e Zd ZdZddddddddddejdddfddZdd Zdd	 Z	d
d Z
dd Zdd Zdd Zd+ddZd,ddZd-ddZd.ddZd/ddZd0ddZd1dd Zd2d!d"Zd#d$ Zd%d& Zd'd( Zd)d* ZdS )3ReplayContextaW  State/Context for a conversation between an simulated client and a
       server. Some of the context is shared amongst all conversations
       and should be generated before the fork, while other context is
       specific to a particular conversation and should be generated
       *after* the fork, in generate_process_local_config().
    NZDOMAINc                 C   s   || _ d | _|| _|| _|r$t| _nt| _|	| _|
| _|| _	|| _
|| _|| _|d| _|| _|| _d| _d| _d| _d| _d| _d| _d| _d| _|| _|   d S )NrealmF)servernetlogon_connectioncredslpr   kerberos_stater   oubase_dndomainstatsdirglobal_tempdir
domain_sidgetr   instance_idbadpassword_frequencylast_lsarpc_badlast_lsarpc_named_badlast_simple_bind_badlast_bind_badlast_srvsvc_badlast_drsuapi_badlast_netlogon_badZlast_samlogon_badtotal_conversationsgenerate_ldap_search_tables)r   r   r   r   r   r   Zprefer_kerberostempdirr   r   r   r   r   r   rY   rY   rZ   r   b  s4    zReplayContext.__init__c                 C   s  t  }td| j || j| jd}|j| tjdgdgd}i }dg i}|D ]Z}t	|j
}ddd	 |dD  }||g }	|	| |d
rL|d | qLt| D ]}
|
dd  dkrq|
d d }|dd  dkr|d d }qtdD ]D}|d7 }||
kr4||v r4td|
|f tjd q||
 ||< qq|| _|| _i | _|j| tjdgdd}ddd	 |D }d|| jd< d}dD ]}|d|| 7 }qd|| jd< d| jd< |jdtjdgd}d|d d | jd< d S ) N	ldap://%s)urlsession_infocredentialsr   zpaged_results:1:1000dn)scopeZcontrolsattrsZinvocationId,c                 s   s   | ]}|  d d V  qd S )Nr$   )lstrip.0ro   rY   rY   rZ   	<genexpr>      z<ReplayContext.generate_ldap_search_tables.<locals>.<genexpr>zCN=NTDS Settings,rL   z,DC   zdn_map collison %s %srO   z"(objectclass=groupPolicyContainer))r   r   
expressionr   c                 s   s   | ]}d  |d V  qdS )z(distinguishedName={0})r   N)format)r   rW   rY   rY   rZ   r     r   z(|{0})ZgPCFileSysPath)zDomain Controllers,ztraffic_replay,r   z(distinguishedName={0}{1})ZgpLinkz'(objectCategory=pKICertificateTemplate)ZpKIExtendedKeyUsageZhighestCommittedUSN)r   r   z(usnChanged>={0})r   Z
usnChanged)r   r   r   r   r   search	domain_dnldbZSCOPE_SUBTREEstrr   r   r   upper
setdefaultappend
startswithlistkeysrangerR   rS   rT   dn_mapattribute_clue_mapsearch_filtersr   Z
SCOPE_BASE)r   sessiondbresr   r   rr   patternr(   krm   iZ
gpos_by_dnZou_strr   rY   rY   rZ   r     sh    




z)ReplayContext.generate_ldap_search_tablesc                 C   sT   | j  D ]}||v r
| j |   S q
|dkrPt | j }t| j|}d| S dS )NzDC,DCz((&(sAMAccountName=%s)(objectClass=user))z(objectClass=*))r   r   randomr   	user_namer   )r   r   Zdn_sigr   r   Zrandom_user_idZaccount_namerY   rY   rZ   guess_search_filter  s    z!ReplayContext.guess_search_filterc                 C   s   g | _ g | _g | _g | _g | _g | _g | _|j| _|j| _|j	| _	|j
| _
t| jd|j | _| jd| j | jd| j | jd| j | jdd d| _d| j| jf | _d| j	| jf | _|   |   d S )	Nzconversation-%dzprivate dirzlock dirzstate directoryztls verify peerZno_checkz/root/ncalrpc_as_systemcn=%s,%s)ldap_connectionsdcerpc_connectionslsarpc_connectionslsarpc_connections_nameddrsuapi_connectionssrvsvc_connectionssamr_contextsnetbios_namemachinepassusernameuserpassmk_masked_dirr   r   r   r   setZremoteAddressr   Zsamlogon_dnuser_dngenerate_machine_credsgenerate_user_creds)r   accountr   rY   rY   rZ   generate_process_local_config  s:    

z+ReplayContext.generate_process_local_configc                 C   sR   |sB| j r>t | j k r>z|| W n ty6   Y n0 d}nd}||}||fS )a  Execute the supplied logon function, randomly choosing the
           bad credentials.

           Based on the frequency in badpassword_frequency randomly perform the
           function with the supplied bad credentials.
           If run with bad credentials, the function is re-run with the good
           credentials.
           failed_last_time is used to prevent consecutive bad credential
           attempts. So the over all bad credential frequency will be lower
           than that requested, but not significantly.
        TF)r   r   r   )r   fZgoodZbadZfailed_last_timeresultrY   rY   rZ   with_random_bad_credentials  s    z)ReplayContext.with_random_bad_credentialsc                 C   s  t  | _| j| j | j| j | j| j | j| j	 | j
| j | j| j t  | _| j| j | j| j | j| jdd  | j| j	 | j| j t  | _| j| j | j| j | j| j | j| j	 | j| j tjB  | j| j | j| j t  | _| j| j | j| j | j| jdd  | j| j	 | j| j tjB  | j| j | j| j dS )a;  Generate the conversation specific user Credentials.

        Each Conversation has an associated user account used to simulate
        any non Administrative user traffic.

        Generates user credentials with good and bad passwords and ldap
        simple bind credentials with good and bad passwords.
        N)r   
user_credsguessr   set_workstationr
  set_passwordr  set_usernamer  
set_domainr   set_kerberos_stater   user_creds_badsimple_bind_credsZset_gensec_featuresZget_gensec_featuresr    ZFEATURE_SEALZset_bind_dnr  simple_bind_creds_badr   rY   rY   rZ   r  2  sF    	z!ReplayContext.generate_user_credsc                 C   s   t  | _| j| j | j| j | jt | j| j	 | j
| jd  | j| j | j| j t  | _| j| j | j| j | jt | j| j	dd  | j
| jd  | j| j dS )zGenerate the conversation specific machine Credentials.

        Each Conversation has an associated machine account.

        Generates machine credentials with good and bad passwords.
        $Nr  )r   machine_credsr  r   r  r
  Zset_secure_channel_typer   r  r  r  r  r   r  r   machine_creds_badr   rY   rY   rZ   r  `  s    z$ReplayContext.generate_machine_credsc                 C   sT   | j |}|rt|S | }|rN|| jv r@t| j| S |dd  }q"| jS )N   )r   r   r   choicer   r   r   )r   r   Z
attributesZ	attr_cluerY   rY   rZ   get_matching_dny  s    	

zReplayContext.get_matching_dnFc                 C   s@   d}| j r|s| j d S td| j |df| j}| j | |S )Nz$12345678-1234-abcd-ef00-01234567cffbzncacn_ip_tcp:%sr]   )r  r   r   r   r   )r   newZguidcrY   rY   rZ   get_dcerpc_connection  s    



z#ReplayContext.get_dcerpc_connectionc                    sL    j r|s j d S  fdd} | j j j\} _ j | |S )Nr)  c                    s   t  d j  j| S Nzncacn_np:%s)r   r   r   r   r   rY   rZ   connect  s    z4ReplayContext.get_srvsvc_connection.<locals>.connect)r  r  r  r   r   r   r   r*  r/  r+  rY   r   rZ   get_srvsvc_connection  s    

z#ReplayContext.get_srvsvc_connectionc                    sL    j r|s j d S  fdd} | j j j\} _ j | |S )Nr)  c                    s   d}t d j|f  j| S )Nzschannel,seal,signncacn_ip_tcp:%s[%s]r   lsarpcr   r   )r   binding_optionsr   rY   rZ   r/    s    z4ReplayContext.get_lsarpc_connection.<locals>.connect)r  r  r$  r%  r   r   r0  rY   r   rZ   get_lsarpc_connection  s    

z#ReplayContext.get_lsarpc_connectionc                    sL    j r|s j d S  fdd} | j j j\} _ j | |S )Nr)  c                    s   t d j  j| S r-  r3  r.  r   rY   rZ   r/    s    z?ReplayContext.get_lsarpc_named_pipe_connection.<locals>.connect)r  r  r$  r%  r   r   r0  rY   r   rZ    get_lsarpc_named_pipe_connection  s    

z.ReplayContext.get_lsarpc_named_pipe_connectionc                    sd    j r|s j d }|S  fdd} | j j j\} _t|\}}||f} j | |S )zget a (drs, drs_handle) tupler)  c                    s"   d}d j |f }t| j| S )NZsealr2  )r   r   r   )r   r5  Zbinding_stringr   rY   rZ   r/    s
    z:ReplayContext.get_drsuapi_connection_pair.<locals>.connect)r  r  r  r   r   r   r   )r   r*  Zunbindr+  r/  ZdrsZ
drs_handleZsupported_extensionsrY   r   rZ   get_drsuapi_connection_pair  s    

z)ReplayContext.get_drsuapi_connection_pairc                    sz    j r|s j d S  fdd} fdd}|rN | j j j\} _n | j j j\} _ j | |S )Nr)  c                    s   t d j |  jdS )a$  
            To run simple bind against Windows, we need to run
            following commands in PowerShell:

                Install-windowsfeature ADCS-Cert-Authority
                Install-AdcsCertificationAuthority -CAType EnterpriseRootCA
                Restart-Computer

            z
ldaps://%sr   r   r   r   r   r.  r   rY   rZ   simple_bind  s    

z6ReplayContext.get_ldap_connection.<locals>.simple_bindc                    s   t d j |  jdS )Nr   r9  r:  r.  r   rY   rZ   	sasl_bind  s    
z4ReplayContext.get_ldap_connection.<locals>.sasl_bind)	r  r  r!  r"  r   r  r   r   r   )r   r*  simpler;  r<  ZsamdbrY   r   rZ   get_ldap_connection  s&    


z!ReplayContext.get_ldap_connectionc                 C   s0   | j r
|r&| j t| j| j| jd | j d S )N)r   r   r)  )r	  r   SamrContextr   r   r   )r   r*  rY   rY   rZ   get_samr_context  s
    
zReplayContext.get_samr_contextc                    s>    j r j S  fdd} | j j j\} _| _ |S )Nc                    s   t  d j  j| S )Nzncacn_ip_tcp:%s[schannel,seal])r   r   r   r.  r   rY   rZ   r/    s    z6ReplayContext.get_netlogon_connection.<locals>.connect)r   r  r$  r%  r   )r   r/  r+  rY   r   rZ   get_netlogon_connection  s    z%ReplayContext.get_netlogon_connectionc                 C   s
   | j dfS )NAr   r   rY   rY   rZ   guess_a_dns_lookup%  s    z ReplayContext.guess_a_dns_lookupc                 C   s>   | j  }t }dd |d D |j_|d |_t }||fS )Nc                 S   s"   g | ]}t |tr|nt|qS rY   )
isinstancer   ordr   rY   rY   rZ   
<listcomp>+  s   z3ReplayContext.get_authenticator.<locals>.<listcomp>Z
credentialrw   )r$  Znew_client_authenticatorr   Zcreddatarw   )r   ZauthZcurrentZ
subsequentrY   rY   rZ   get_authenticator(  s    


zReplayContext.get_authenticatorc                 K   sL   t j| j|}t|d}| D ]\}}td||f |d q"|  dS )zWrite arbitrary key/value pairs to a file in our stats directory in
        order for them to be picked up later by another process working out
        statistics.wz%s: %srO   N)ospathr   r   openitemsrR   close)r   filenamekwargsr  r   vrY   rY   rZ   write_stats2  s
    
zReplayContext.write_stats)N)F)F)F)F)FF)FF)F)rr   rs   rt   r   rK  environr   r   r   r  r  r  r  r  r(  r,  r1  r6  r7  r8  r>  r@  rA  rD  rI  rS  rY   rY   rY   rZ   r   [  sB   

,W.

	




&

r   c                   @   s*   e Zd ZdZd	ddZdd Zdd ZdS )
r?  z5State/Context associated with a samr connection.
    Nc                 C   s@   d | _ d | _d | _d | _d | _d | _d | _|| _|| _|| _	d S r   )

connectionhandleZdomain_handler   Zgroup_handleZuser_handleZridsr   r   r   )r   r   r   r   rY   rY   rZ   r   @  s    zSamrContext.__init__c                 C   s(   | j s"tjd| j | j| jd| _ | j S )Nzncacn_ip_tcp:%s[seal])Zlp_ctxr   )rU  r   r   r   r   r   rY   rY   rZ   get_connectionL  s    zSamrContext.get_connectionc                 C   s$   | j s|  }|d tj| _ | j S r   )rV  rW  ZConnect2r   ZSEC_FLAG_MAXIMUM_ALLOWED)r   r+  rY   rY   rZ   
get_handleU  s    zSamrContext.get_handle)NN)rr   rs   rt   r   r   rW  rX  rY   rY   rY   rZ   r?  =  s   
	r?  c                   @   s   e Zd ZdZdddZdd Zdd	 Zd ddZdd ZeZ	dd Z
dd Zdd Zdd Zd!ddZd"ddZdd Zdd ZdS )#ConversationzADetails of a converation between a simulated client and a server.NrY   c                 C   s@   || _ || _g | _t|| _d| _|| _|D ]}| j|  q,d S )Nr   )
start_timer   packetsrp   rW   client_balancer   add_short_packet)r   rZ  r   seqr   rm   rY   rY   rZ   r   ^  s    
zConversation.__init__c                 C   s6   | j d u r|j d u rdS dS |j d u r*dS | j |j  S )Nr   r)  r]   )rZ  r   rY   rY   rZ   r   i  s    


zConversation.__cmp__c                 C   s   |  }| jdu r|j| _| jdu r,|j| _|j| jkrLtd| j|jf | j| j8  _|j|jd kr|  j| 8  _n|  j| 7  _| r| j	
| dS )zmAdd a packet object to this conversation, making a local copy with
        a conversation-relative timestamp.Nz8Conversation endpoints %s don't matchpacket endpoints %sr   )r   rZ  rw   r   rq   rz   r\  r   r   r[  r   )r   packetrm   rY   rY   rZ   
add_packetr  s    


zConversation.add_packetTc              
   C   s   |rt ||sdS |  \}}|s,|| }}||f}	t|	d}
t|d}t|| j |d|||||
|	}|j|jd kr|  j	|
 8  _	n|  j	|
 7  _	| r| j| dS )zCreate a packet from a timestamp, and 'protocol:opcode' pair, and a
        (possibly empty) list of extra data. If client is True, assume
        this packet is from the client to the server.
        Nr   06r   )r   guess_client_serverOP_DESCRIPTIONSr   IP_PROTOCOLSru   rZ  rz   r   r\  r   r   r[  r   )r   rw   r|   r}   r   clientZskip_unused_packetsrz   r{   r   r~   rx   r_  rY   rY   rZ   r]    s"    
zConversation.add_short_packetc                 C   s   d| j | j| jt| jf S )Nz-<Conversation %s %s starting %.3f %d packets>)r   r   rZ  lenr[  r   rY   rY   rZ   r     s
    zConversation.__str__c                 C   s
   t | jS r   )iterr[  r   rY   rY   rZ   __iter__  s    zConversation.__iter__c                 C   s
   t | jS r   )rf  r[  r   rY   rY   rZ   __len__  s    zConversation.__len__c                 C   s*   t | jdk rdS | jd j| jd j S )Nr$   r   r)  )rf  r[  rw   r   rY   rY   rZ   get_duration  s    zConversation.get_durationc                    s    fdd j D S )Nc                    s   g | ]}|  jqS rY   )r   rZ  r   rm   r   rY   rZ   rG    r   z8Conversation.replay_as_summary_lines.<locals>.<listcomp>)r[  r   rY   r   rZ   replay_as_summary_lines  s    z$Conversation.replay_as_summary_linesc                 C   s   | j }t | }|| }|t }|dkr4t| t | | }| d| |f  d}	d}
t }| jD ]z}t | }||j }||	kr|}	|dk r| t }|dkrt| t | }||j |
kr||j }
|| | ql|	||
fS )zMReplay the conversation at the right time.
        (We're already in a fork).r   zstarting %s [miss %.3f]r   )rZ  r   SLEEP_OVERHEADsleeprW   r[  rw   r   )r   r   r   r  r   nowgap
sleep_timeZmissZmax_gapmax_sleep_missZp_startrm   rY   rY   rZ   replay_with_delay  s2    





zConversation.replay_with_delayc                 C   s>   | j \}}| jdk r||fS | jdkr6||kr6||fS ||fS )zhHave a go at deciding who is the server and who is the client.
        returns (client, server)
        r   )r   r\  )r   Zserver_cluerd   brY   rY   rZ   rb    s    

z Conversation.guess_client_serverc                    s4    fdd| j D | _ | j r*| j d jnd| _dS )zPrune any packets outside the timne window we're interested in

        :param s: start of the window
        :param e: end of the window
        c                    s*   g | ]"}|j   kr krn q|qS rY   r   rk  r   rn   rY   rZ   rG    r   z>Conversation.forget_packets_outside_window.<locals>.<listcomp>r   Nr[  rw   rZ  )r   rn   r   rY   ru  rZ   forget_packets_outside_window  s    z*Conversation.forget_packets_outside_windowc                 C   s6   | j D ]}| j|8  _q| jdur2|  j|8  _dS )z=Adjust the packet start times relative to the new start time.Nrv  )r   rZ  rm   rY   rY   rZ   renormalise_times  s    

zConversation.renormalise_times)NNrY   N)TT)NN)N)rr   rs   rt   r   r   r   r`  r]  r   r   rh  ri  rj  rl  rs  rb  rw  rx  rY   rY   rY   rZ   rY  \  s$     
	 

#
	rY  c                   @   s6   e Zd ZdZdddZdd ZdddZdd	d
ZdS )	DnsHammerzOA lightweight conversation that generates a lot of dns:0 packets on
    the flyNc                    sR   t |  } fddt|D | _| j  || _ | _d| _| j|d| _d S )Nc                    s   g | ]}t d  qS )r   )r   uniform)r   r   r   rY   rZ   rG  	  r   z&DnsHammer.__init__.<locals>.<listcomp>r   
query_file)	r   r   timessortrater   rZ  _get_query_choicesquery_choices)r   dns_rater   r}  nrY   r{  rZ   r     s    
zDnsHammer.__init__c                 C   s   dt | j| j| jf S )Nz-<DnsHammer %d packets over %.1fs (rate %.2f)>)rf  r~  r   r  r   rY   rY   rZ   r     s    zDnsHammer.__str__c                 C   s   |rt |d}| }W d   n1 s,0    Y  g }| D ]>}| }|rB|dsB|d}t|dksvJ || qB|S g dS dS )z
        Read dns query choices from a file, or return default

        rname may contain format string like `{realm}`
        realm can be fetched from context.realm
        r   N#r      )
)r   {realm}rB  yes)r]   r  NSr  )r$   	*.{realm}rB  no)r&  r  r  r  )
   _msdcs.{realm}rB  r  )   r  r  r  )   nx.realm.comrB  r  )   r  r  r  )   *.nx.realm.comrB  r  )   r  r  r  )rM  read
splitlinesstripr   r   rf  r   )r   r}  r  textchoicesr   rX   rY   rY   rZ   r    s    &
zDnsHammer._get_query_choicesc                 C   s  |sJ |j sJ t }| jD ]}t | }|| }|t }|dkrRt| t| j\}}}	}
|j|j d}d}t }zbz"t	||	}|
dkrt
|sd}W n ty   d}Y n0 W t }|| }td||||f  q t }|| }td||||f  0 q d S )Nr   rC  Tr  Fz%f	DNS	dns	%s	%f	%s	)r   r   r~  rm  rn  r   r'  r  r   	dns_queryrf  r   rR   )r   r   r   r   ro  rp  rq  r}   ZrnameZrtypeZexistZsuccessZpacket_startZanswersr_   r   rY   rY   rZ   replay5  s2    



zDnsHammer.replay)N)N)N)rr   rs   rt   r   r   r   r  r  rY   rY   rY   rZ   ry    s
   
	
!ry  countc                 C   sv  t t}g }| D ]x}t|tr&t|}td|jf tjd |D ]>}t	
|}|jdkrt|dkrt||j  d7  < q@|| q@|  q|sg dfS tdd |D }td	d |D }td
tjd t }	t|D ]N\}
}| j|8  _|	|j}|du rt|
d d}||	|j< || qg }|	 D ]}t|dkr2|| q2t|| }t|	| }||||fS )zLLoad a summary traffic summary file and generated Converations from it.
    zIngesting %srO   r(   Zincluder]   r   c                 s   s   | ]}|j V  qd S r   r   rk  rY   rY   rZ   r   g  r   z#ingest_summaries.<locals>.<genexpr>c                 s   s   | ]}|j V  qd S r   r   rk  rY   rY   rZ   r   h  r   z$gathering packets into conversationsNr$   )r   )r   r   rE  r   rM  rR   rN   rS   rT   ru   r   r|   r}   r   rO  minmaxr   	enumeraterw   r   r   rY  r`  valuesrf  r   )filesZdns_modeZ
dns_countsr[  r  r   rm   rZ  Zlast_packetconversationsr   r+  Zconversation_listr   Zmean_intervalrY   rY   rZ   ingest_summariesQ  s@    




r  c                 C   s2   t  }| D ]}||j q
|r.|dd S d S )Nr]   r   )r   updater   most_common)r  Z	addressesr+  rY   rY   rZ   guess_server_address  s
    r  c                 C   s,   i }|   D ]\}}d|}|||< q|S Nr   )rN  r   )ro   yr   rR  Zk2rY   rY   rZ   stringify_keys  s
    

r  c                 C   s4   i }|   D ]"\}}tt|d}|||< q|S r  )rN  rU   r   r   )ro   r  r   rR  r   rY   rY   rZ   unstringify_keys  s
    
r  c                   @   sV   e Zd ZdddZi fddZdd Zdd	 ZdddZdd Zdd Z	dddZ
dS )TrafficModelr&  c                 C   s0   i | _ i | _|| _tt| _d| _ddg| _d S )Nr   r   r]   )ngramsquery_detailsr  r   r   dns_opcountscumulative_durationpacket_rate)r   r  rY   rY   rZ   r     s    
zTrafficModel.__init__c              	   C   s  d}d}t f| jd  }t|}| D ]\}}| j|  |7  < q(t|dkr|d j}	d}
|	d }|D ]"}|
t|7 }
t||jd j	}qj|
| j
d< ||	 | j
d< |D ]}||\}}|| 7 }t f| jd  }|D ]}|j|krq|j	| }|j	}|tkrDdttd|t  }| j|g | |dd  |f }| }| j|g t|j | j|g | |dd  |f }qq|  j|7  _| j|g t  d S )Nr   r]   r   g?r)  wait:%dr&   )
NON_PACKETr  r  rN  r  rf  rZ  r  r[  rw   r  rb  rj  rz   WAIT_THRESHOLDmathlog
WAIT_SCALEr  r   r   r   r  rU   r   r  )r   r  r  prevZcum_durationr   r   r   rR  firsttotallastr+  re  rm   elapsedr   Zshort_prY   rY   rZ   learn  sP    





zTrafficModel.learnc                 C   s   i }| j  D ]"\}}d|}tt|||< qi }| j D ]"\}}ttdd |D ||< q@||| j| jtd}| j	|d< t
|trt|d}tj||dd d S )	Nr   c                 s   s    | ]}|rd  |ndV  qdS )r   r%   N)r   r   rY   rY   rZ   r     s   z$TrafficModel.save.<locals>.<genexpr>)r  r  r  r  versionr(   rJ  r$   )indent)r  rN  r   dictr   r  r  r  CURRENT_MODEL_VERSIONr  rE  r   rM  jsondump)r   r  r  r   rR  r  drY   rY   rZ   save  s&    




zTrafficModel.savec           	      C   s  t |trt|}t|}z$|d }|tk r>td|tf W n ty^   tdt Y n0 |d  D ]V\}}t	t|
d}| j|g }| D ]\}}|t|g|  q|  ql|d  D ]n\}}| jt|g }| D ]B\}}|dkr|dg|  q|t	t|
dg|  q|  qd	|v rt|d	  D ]\}}| j|  |7  < qV|d
 | _|d | _d S )Nr  z4the model file is version %d; version %d is requiredz=the model file lacks a version number; version %d is requiredr  r   r  r%   rY   r(   r  r  )rE  r   rM  r  loadREQUIRED_MODEL_VERSION
ValueErrorKeyErrorrN  rU   r   r  r   extendr  r  r  r  r  )	r   r  r  r  r   rR  r  rm   r  rY   rY   rZ   r    s>    




 


zTrafficModel.loadr   Nr]   r   c                 C   s  g }t f| jd  }|du r$|d }t| j|t f}|t kr||k rNqt |krttd||f tjd qdt	dd }td| tjd || j
v rt| j
| }	ng }	|d	d\}
}|
d
krt|t  }t|t|  }||7 }nTtjt }t|| }||7 }|dur2||kr2q||krN|||
||	f |dd |f }|d dd dkr$|d dd dkr$t f| jd  }q$|S )zUConstruct an individual conversation packet sequence from the
        model.
        r]   Nz"ending after %s (persistence %.1f)rO   r  r      ztrying %s instead of end:r   zwait:r)  )r  r  r   r'  r  r   rR   rS   rT   Z	randranger  r   r   r  Zexpr  rz  NO_WAIT_LOG_TIME_RANGEr   )r   rw   	hard_stopreplay_speedignore_beforepersistencer+  r   rm   r   r|   r}   Zlog_wait_timer   Zlog_waitrY   rY   rZ   construct_conversation_sequence  sD    



(z,TrafficModel.construct_conversation_sequencec                 C   s   | j \}}|| | S r   r  )r   scalerate_nrate_trY   rY   rZ   scale_to_packet_rateO  s    
z!TrafficModel.scale_to_packet_ratec                 C   s   | j \}}|| | S r   r  )r   Zppsr  r  rY   rY   rZ   packet_rate_to_scaleS  s    
z!TrafficModel.packet_rate_to_scalec                 C   s   d| }t || }g }d}||k rt| |}	| j|	||d|d}
|
D ]\}}}}t||rJ qhqJq||
 |t|
7 }q| |}td||t|||f t	j
d |  |S )z<Generate a list of conversation descriptions from the model.	   r   )r  r  r  r  zGwe have %d packets (target %d) in %d conversations at %.1f/s (scale %f)rO   )r   r   rz  r  r   r   rf  r  rR   rS   rT   r  )r   r  r   r  r  Zlead_inZtarget_packetsr  Z	n_packetsr   r+  rw   r|   r}   r   r  rY   rY   rZ   generate_conversation_sequencesW  s8    	



z,TrafficModel.generate_conversation_sequences)r&  )r   Nr]   r   r   )r]   r   )rr   rs   rt   r   r  r  r  r  r  r  r  rY   rY   rY   rZ   r    s   
0(     
6  r  r]   c                 C   s@   g }| D ]2}|rt |d d ||f|}|d7 }|| q|S )Nr   r]   )rY  r   )r^  r   re  r  rn   r+  rY   rY   rZ   seq_to_conversations  s    r  r6   ra  )r(   rpc_netlogonr   r+   rK   r-   r3   r4  r   r5   epmr   rI   rJ   r   r:   zHost Announcement (0x01)zRequest Announcement (0x02)zBrowser Election Request (0x08)zGet Backup List Request (0x09)z$Domain/Workgroup Announcement (0x0c)z Local Master Announcement (0x0f)ZsearchRequestZsearchResDoneZRequestZBindZBind_ackZBind_nakZAlter_contextZAlter_context_respZAUTH3ZResponser
   ZresponseZDsBindZDsCrackNamesZDsWriteAccountSpnZDsUnbindZDsReplicaSyncZDsGetNCChangesZDsReplicaUpdateRefsZMapr   ZbindRequestZbindResponseZunbindRequestZsearchResEntryz*** Unknown ***Zlsa_LookupNamesZlsa_LookupSidsZlsa_QueryTrustedDomainInfoBySidZlsa_SetTrustedDomainInfoZlsa_OpenPolicyZlsa_LookupSids3Zlsa_LookupNames4ZNetrLogonDummyRoutine1ZNetrServerAuthenticate3ZNetrLogonGetDomainInfoZNetrServerPasswordSet2ZNetrLogonSamLogonExZDsrEnumerateDomainTrustsZNetrLogonSamLogonWithFlagsZNetrServerReqChallengeZConnectZGetAliasMembershipZLookupNamesZ
LookupRidsZ	OpenGroupZCloseZQueryGroupMemberZOpenUserZQueryUserInfoZGetGroupsForUserZQuerySecurityZLookupDomainZConnect5ZEnumDomainsZ
OpenDomainZQueryDomainInfozClose (0x04)zLocking AndX (0x24)zRead AndX (0x2e)zTrans2 (0x32)zTree Disconnect (0x71)zNegotiate Protocol (0x72)zSession Setup AndX (0x73)zLogoff AndX (0x74)zTree Connect AndX (0x75)zNT Create AndX (0xa2)ZNegotiateProtocolZIoctlZFindZGetInfoZBreakZSessionSetupZSessionLogoffZTreeConnectZTreeDisconnectZCreateZReadz$SAM LOGON request from client (0x12)z3SAM Active Directory Response - user unknown (0x17)ZNetShareGetInfoZNetSrvGetInfo)])rI   Z0x01)rI   Z0x02)rI   Z0x08)rI   Z0x09)rI   Z0x0c)rI   Z0x0fr2   rB   )r5   r)   r4   rC   rE   r7   rG   r   )r5   r1   r'   r;   )r   r)   )r   rD   )r   rF   )r   r<   )r   r1   )r   r/   )r   r?   )r  r/   r   r,   r=   r0   r.   r>   r@   )r-   r   )r4  r8   )r4  rH   )r4  39)r4  40)r4  6)r4  Z76)r4  Z77r9   )r:   r<   )r  21)r  Z26)r  Z29)r  Z30)r  r  )r  r  )r  Z45)r  r?   )r   r)   )r   r   )r   Z17)r   18)r   Z19)r   r<   )r   Z25)r   Z34)r   Z36)r   r  )r   r/   )r   rA   )r   Z64)r   r  )r   7)r   8)r+   Z0x04)r+   Z0x24)r+   Z0x2e)r+   Z0x32)r+   Z0x71r*   )r+   Z0x73)r+   Z0x74)r+   Z0x75)r+   Z0xa2)rK   r)   )rK   r6   )rK   r8   )rK   r   )rK   r  )rK   r<   )rK   r1   )rK   r/   )rK   r?   )rK   rA   )rK   r  )rK   r  )rJ   Z0x12)rJ   Z0x17)r   r   )r   r  c           
      C   sT   |  dd\}}t||fd}t|d}||d|||||g}	|	| d|	S )Nr  r]   r   ra  r   )r   rc  r   rd  r  r   )
rm   rw   rz   r{   r   r|   r}   r~   rx   r   rY   rY   rZ   expand_short_packet  s    
r  c                 C   s"   t j  t j  td dS )zSignal handler closes standard out and error.

    Triggered by a sigterm, ensures that the log messages are flushed
    to disk and not lost.
    r   N)rS   rT   rO  stdoutrK  _exit)signalframerY   rY   rZ   flushing_signal_handler  s    

r  c              
   C   s  |d t dd }tj  tj  t }|dkr<|S zz@t | ||f}d}	| d d }
t	|
|| |d}t

t
jt ||| tj  td tj|jd|j }t|d}ztj  td W n4 ty } ztd|  W Y d	}~n
d	}~0 0 |t_t | }|
| }|t }|dkrHt| |j||d
\}}}td|  td|  td|  W nH ty   d}	tdt |f tjd t tj tj  Y n0 W tj  tj  t!|	 n tj  tj  t!|	 0 d	S )z8Fork a new process and replay the conversation sequence.  r   i  )r^  r   zstats-conversation-%drJ  r]   stdout closing failed with %sN)r   r   zMaximum lag: %fzStart lag: %fzMax sleep miss: %fz*EXCEPTION in child PID %d, conversation %srO   )"r   ZrandintrS   r  rb   rT   rK  forkseedrY  r  SIGTERMr  r  stdinrO  rL  r   r   r   rM  IOErrorr   infor   rm  rn  rs  rR   r   getpidr`   	print_excr  )csr   r   r  	client_idZ	server_idr  pidr   statusr   r+  rP  r  r   ro  rp  rq  Zmax_lagZ	start_lagrr  rY   rY   rZ   replay_seq_in_fork  sf    












r  c           	   
   C   sX  t j  t j  t }|dkr(|S t j  td zt j  td W n2 ty } zt	
d|  W Y d }~n
d }~0 0 tj|jd}t|dt _zz0d}ttjt t| ||d}|j|d W n: ty   d}tdt  t jd	 tt j Y n0 W t j  t j  t| n t j  t j  t| 0 d S )
Nr   r]   r  z	stats-dnsrJ  r|  )r   z)EXCEPTION in child PID %d, the DNS hammerrO   )rS   r  rb   rT   rK  r  r  rO  r  r   warnrL  r   r   rM  r  r  r  ry  r  r   rR   r  r`   r  r  )	r  r   r   r}  r  r   rP  r  ZhammerrY   rY   rZ   dnshammer_in_forkS  s@    








r  Fc
                 K   s<  t f |||t| d|
}t|t| k rDtdt|t| f t  t| d }t | }|d u r| d d d | }td| tjd td||  tjd td	| tjd || d
 }t	
dt| |f  |jdt| tdd | D d i }zZzP|r(t||||d}d||< t| D ]2\}}|| }|d }t|||||}|||< q0t }td|| | || f tjd t |k rV|rVtd ztdtj\}}W nB ty } z(|jtkr W Y d }~qVW Y d }~n
d }~0 0 |r||d }tdkr>td||t|f tjd |	r|dkrqVqW n* ty   tdtjd t  Y n0 W |jdt|d dD ]l}tdt||f tjd |D ]L}zt|| W n4 ty } z|jtkr W Y d }~n
d }~0 0 qtd t d }|rztdtj\}}W n4 tyt } z|jtkr` W Y d }~n
d }~0 0 |dkr||d }|d u rtd|  tj  tj  td td||t|f tjd t |kr$qq$|s qtd q|r(tdt| tjd zt dd W n" t!yZ   tdtjd Y n0 n|jdt|d dD ]l}tdt||f tjd |D ]L}zt|| W n4 ty } z|jtkr΂ W Y d }~n
d }~0 0 qtd t d }|rztdtj\}}W n4 tyN } z|jtkr: W Y d }~n
d }~0 0 |dkr||d }|d u rtd|  tj  tj  td td||t|f tjd t |krq̐q|s qtd qv|rtdt| tjd zt dd W n" t!y4   tdtjd Y n0 0 d S ) N)r   r   r   r   z(we have %d accounts but %d conversationsg{Gz?r)  r   zWe will start in %.1f secondsrO   zWe will stop after %.1f secondszruntime %.1f secondsr&   z6Replaying traffic for %u conversations over %d secondsZ
intentionsc                 s   s   | ]}t |V  qd S r   )rf  r   rY   rY   rZ   r     r   zreplay.<locals>.<genexpr>)Planned_conversationsPlanned_packetsr|  r]   r$   z,all forks done in %.1f seconds, waiting %.1fg~jth?z-process %d finished conversation %d; %d to gozEXCEPTION in parentZ
unfinished)Unfinished_conversations)   r  r  zkilling %d children with -%d      ?zchildren is %s, no pid foundz)kill -%d %d KILLED conversation; %d to goz%d children are missingzignoring fake ^C)"r   rf  r  rK  setpgrpr   rR   rS   rT   r   r  rS  sumr  r  r  rn  waitpidWNOHANGOSErrorerrnor   poprQ   r   r`   r  killr   rb   r  r  killpgKeyboardInterrupt)Zconversation_seqhostr   r   accountsr  Zdns_query_filer   Zlatency_timeoutZstop_on_any_errorrQ  r   Zdelayr   r_   Zchildrenr  r   r  r  r  r   r  r   r+  rn   rY   rY   rZ   r  v  sP   

$
















r  c                 C   s"   t  }td|  |dg||d}|S )Nr   zmodules:paged_searches)r   r   Zoptionsr   r   )r   r   )r  r   r   r   r   rY   rY   rZ   openLdb	  s    r  c                 C   s   d||   f S )z(Generate an ou name from the instance idz#ou=instance-%d,ou=traffic_replay,%s)r   )r   r   rY   rY   rZ   ou_name  s    r  c              
   C   s   t | |}z | |ddd dd W n8 tyb } z |j\}}|dkrN W Y d}~n
d}~0 0 z| |dd W n8 ty } z |j\}}|dkr W Y d}~n
d}~0 0 |S )zCreate an ou, all created user and machine accounts will belong to it.

    This allows all the created resources to be cleaned up easily.
    r   r]   Zorganizationalunit)r   objectclassD   N)r  addr   r   rX   r   r   r   r   r  _rY   rY   rZ   	create_ou  s$    


r  ConversationAccounts)r
  r  r  r  c           	      C   sH   g }t d|d D ]0}t||}t||}t||||}|| q|S )z;Generate a series of unique machine and user account names.r]   )r   machine_namer   r  r   )	r   r   numberpasswordr  r   r
  r  r  rY   rY   rZ   generate_replay_accounts=  s    

r  Tc           	      C   s`   t | |}d||f }dt| d}|r:tttB }ntt}| |dd| ||d dS )z"Create a machine account via ldap.r  "%s"	utf-16-lecomputerz%s$r   r  sAMAccountNameZuserAccountControlZ
unicodePwdN)r  r"   encoder   r   r   r   r  )	r   r   r
  r  traffic_accountr   r   utf16pwZaccount_controlsrY   rY   rZ   create_machine_accountK  s    
r"  c                 C   s\   t | |}d||f }dt| d}| |d|tt|d t| }||d dS )zCreate a user account via ldap.r  r  r  userr  z(A;;WP;;;PS)N)	r  r"   r  r  r   r   r!   ZSDUtilsZdacl_add_ace)r   r   r  r  r   r  r!  ZsdutilsrY   rY   rZ   create_user_accountd  s    
	
r$  c                 C   s,   t | |}d||f }| |d|d dS )zCreate a group via ldap.r  group)r   r  r  N)r  r  )r   r   rN   r   r   rY   rY   rZ   create_groupv  s    
r&  c                 C   s   d| |f S )z-Generate a user name based in the instance idz
STGU-%d-%drY   r   r   rY   rY   rZ   r     s    r   r#  r  c                    s(   | j d| gd} fdd|D S )z'Seach objectclass, return attr in a setz(objectClass={}))r   r   c                    s   h | ]}t |  qS rY   )r   )r   objattrrY   rZ   	<setcomp>  r   z%search_objectclass.<locals>.<setcomp>)r   r   )r   r  r*  ZobjsrY   r)  rZ   search_objectclass  s
    r,  c                 C   sl   t | dd}d}t|ddD ]J}t||}||vrt| ||| |d7 }|d dkrtd||f  q|S )zAdd users to the serverr#  r  r   r)  r]   2   zCreated %u/%u users)r,  r   r   r$  r   r  )r   r   r  r  existing_objectsZusersr   rN   rY   rY   rZ   generate_users  s    
r0  c                 C   s    |rd| |f S d| |f S dS )z1Generate a machine account name from instance id.z
STGM-%d-%dzPC-%d-%dNrY   )r   r   r   rY   rY   rZ   r    s    r  c           	      C   st   t | dd}d}t|ddD ]R}t|||}|d |vrt| |||| |d7 }|d dkrtd||f  q|S )	z"Add machine accounts to the serverr  r-  r   r)  r#  r]   r.  zCreated %u/%u machine accounts)r,  r   r  r"  r   r  )	r   r   r  r  r   r/  addedr   rN   rY   rY   rZ   generate_machine_accounts  s    
r2  c                 C   s   d| |f S )z'Generate a group name from instance id.z
STGG-%d-%drY   r'  rY   rY   rZ   
group_name  s    r3  c                 C   sj   t | dd}d}t|ddD ]H}t||}||vrt| || |d7 }|d dkrtd||f  q|S )z3Create the required number of groups on the server.r%  r-  r   r)  r]   r  zCreated %u/%u groups)r,  r   r3  r&  r   r  )r   r   r  r/  groupsr   rN   rY   rY   rZ   generate_groups  s    
r5  c              
   C   sZ   t | |}z| |dg W n8 tyT } z |j\}}|dkr@ W Y d}~n
d}~0 0 dS )z7Remove the created accounts and groups from the server.ztree_delete:1    N)r  deleter   rX   r  rY   rY   rZ   clean_up_accounts  s    

r8  c	                 C   s   d}	d}
d}t | | td t| |||}td t| ||||}|dkrftd t| ||}
|dkrtd t||
||||}td t| || | }	|
dkr|dkr||
krt	d td|||
|	f  d	S )
zTGenerate the required users and groups, allocating the users to
       those groups.r   zGenerating dummy user accountsz!Generating dummy machine accountszGenerating dummy groupszAssigning users to groupszAdding users to groupsz(The added groups will contain no membersz:Added %d users (%d machines), %d groups and %d membershipsN)
r  r   r  r0  r2  r5  GroupAssignmentsadd_users_to_groupsr  Zwarning)r   r   r  number_of_usersnumber_of_groupsgroup_membershipsmax_membersZmachine_accountsZtraffic_accountsZmemberships_addedgroups_addedZcomputers_addedusers_addedassignmentsrY   rY   rZ   generate_users_and_groups  sF    






rB  c                   @   sd   e Z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S )r9  c                 C   sB   d| _ | | | || || _tt| _| ||||| d S )Nr   )r  generate_group_distributiongenerate_user_distributionr>  r   r   rA  assign_groups)r   r<  r?  r;  r@  r=  r>  rY   rY   rZ   r     s    


zGroupAssignments.__init__c                 C   s@   g }t |}|dkrd S d}|D ]}||7 }|||  q |S )Nr   r   )r  r   )r   weightsZdistr  Z
cumulativeZprobabilityrY   rY   rZ   cumulative_distribution  s    z(GroupAssignments.cumulative_distributionc                 C   sj   |dkrd}n |dkrd}n|dkr*d}nd}g }t d|d D ]}t|}|| q@| || _d	S )
zAProbability distribution of a user belonging to a group.
        i@KL g      @i g      @i g      @g      ?r]   N)r   r   Zparetovariater   rG  	user_dist)r   Z	num_usersZnum_membershipsshaperF  ro   rm   rY   rY   rZ   rD  )  s    	
z+GroupAssignments.generate_user_distributionc                 C   sD   g }t d|d D ]}d|d  }|| q|| _| || _dS )z6Probability distribution of a group containing a user.r]   g?N)r   r   group_weightsrG  
group_dist)r   r  rF  ro   rm   rY   rY   rZ   rC  C  s    z,GroupAssignments.generate_group_distributionc                 C   s,   t  | jt }t  | jt }||fS )z2Returns a randomly generated user-group membership)bisectrH  r   rK  r   r#  r%  rY   rY   rZ   generate_random_membershipQ  s    z+GroupAssignments.generate_random_membershipc                 C   s
   | j | S r   )rA  )r   r%  rY   rY   rZ   users_in_group]  s    zGroupAssignments.users_in_groupc                 C   s
   | j  S r   )rA  r   r   rY   rY   rZ   
get_groups`  s    zGroupAssignments.get_groupsc                 C   sL   t | j| }||krHtd|| d| j|d < | | j}|| _dS )z?Prevent the group's membership from exceeding the max specifiedzGroup {0} has {1} membersr   r]   N)rf  rA  r   r  r   rJ  rG  rK  )r   r%  r>  Znum_membersZnew_distrY   rY   rZ   cap_group_membershipc  s    z%GroupAssignments.cap_group_membershipc                 C   sD   || j | vr,| j | | |  jd7  _| jr@| || j d S )Nr]   )rA  r   r  r>  rQ  rM  rY   rY   rZ   add_assignmento  s
    zGroupAssignments.add_assignmentc           
      C   s   |dkrdS t t|t|t|  }| jr@t|| j| }|| d }|| d }|  |k r|  \}}	|	|ks||krX| |d |	d  qXdS )a  Allocate users to groups.

        The intention is to have a few users that belong to most groups, while
        the majority of users belong to a few groups.

        A few groups will contain most users, with the remaining only having a
        few users.
        r   Nr]   )r  ceilr   r>  r  r  rN  rR  )
r   r<  r?  r;  r@  r=  Zexisting_usersZexisting_groupsr#  r%  rY   rY   rZ   rE  {  s"    zGroupAssignments.assign_groupsc                 C   s   | j S r   )r  r   rY   rY   rZ   r    s    zGroupAssignments.totalN)rr   rs   rt   r   rG  rD  rC  rN  rO  rP  rQ  rR  rE  r  rY   rY   rY   rZ   r9    s   !r9  c           
      C   s   |  }d}d}| D ]}||}t|dkr4qtdt|dD ]T}|||d  }	t| |||	 |t|	7 }|d7 }|d dkrDtd||f  qDqdS )zDTakes the assignments of users to groups and applies them to the DB.r   r  r]   r.  zAdded %u/%u membershipsN)r  rP  rO  rf  r   add_group_membersr   r  )
r   r   rA  r  r  r1  r%  rO  chunkZchunk_of_usersrY   rY   rZ   r:    s    
r:  c           
         s   t | |  fdd}|t||}t }t| ||_|D ]2}|t||}dt| }	t|tj	d||	< q>| 
| dS )z(Adds the given users to group specified.c                    s   d|  f S )Nr  rY   rM   r   rY   rZ   build_dn  s    z#add_group_members.<locals>.build_dnzmember-memberN)r  r3  r   ZMessageZDnr   r   r   ZMessageElementZFLAG_MOD_ADDZmodify)
r   r   r%  rO  rW  Zgroup_dnmr#  r  idxrY   rV  rZ   rT    s    
rT  c           *      C   s  t jj}d}d}d}i }t }t }|dur4|j}	ndd }	|	d dddd}
dddd}t| D ]}tj	| |}t
|dj}|D ]R}z|d	d
}|d }|d }|d }t|d }t|d }t|| |}t||}||f}||g | |d dkr|d7 }n|d7 }||  d7  < || |	| W q ttfy   d|v r|dd\}}||
v rtt||
| |
|< n0||v rtt||| ||< nt|t jd nt|t jd Y q0 qW d   qf1 s0    Y  qf|| }|dkrd}n|| }|dkr4d}n|| }t|}td|  td||f  td||f  t|
 D ]&\}}td|ddd |f  q|t| D ]&\}}td|ddd |f  qtd i }|D ],\}}||vrt ||< || | qt| } | D ]}t|| td}!|!D ]}||f}|| }"t|"}"t|"}#|| }t|"|# }$t|"d}%t|"d}&|"d |"d  }'|"d }(t |d})td |||)|#||$|%|&|'|(f
  q>q&dS )!z/Generate and print the summary stats for a run.r   Nc                 S   s   d S r   rY   )ro   rY   rY   rZ   tw  s    zgenerate_stats.<locals>.twz2time	conv	protocol	type	duration	successful	error
)zMaximum lagz	Start lagzMax sleep miss)r  r  r  r   r   r   r]   r$   r&  r  r   Truer  rO   zTotal conversations:   %10dz-Successful operations: %10d (%.3f per second)z-Failed operations:     %10d (%.3f per second)z%-28s %fr  r^   z%-28s %dzProtocol    Op Code  Description                                Count       Failed         Mean       Median          95%        Range          Max)r   r   gffffff?r)  r   z?%-12s   %4s  %-35s %12d %12d %12.6f %12.6f %12.6f %12.6f %12.6f)!rS   
float_infor  r   r  writerK  listdirrL  r   rM  r   r   r   r  r   r   r  r  
IndexErrorr   rR   rT   rf  sortedrN  replacer   
opcode_keyr  calc_percentilerc  r   )*r   Ztiming_filer  r  Z
successfulZfailedZ	latenciesZfailuresZunique_conversationsr[  Zfloat_valuesZ
int_valuesrP  rL  r  r   r   r   r|   Zpacket_typeZlatencyr   opr   rR  r   Zsuccess_rateZfailure_rater  opsprotor_  Z	protocolsZpacket_typesr  r  ZmeanZmedian
percentilerngZmaxvr~   rY   rY   rZ   generate_stats  s    








8

  



rj  c                 C   s*   zdt |  W S  ty$   |  Y S 0 dS )zCSort key for the operation code to ensure that it sorts numericallyz%03dN)r   r  )rR  rY   rY   rZ   rc  N	  s    rc  c                 C   sp   | sdS t | d | }t|}t|}||kr@| t| S | t| ||  }| t| ||  }|| S )ztCalculate the specified percentile from the list of values.

    Assumes the list is sorted in ascending order.
    r   r]   )rf  r  ZfloorrS  r   )r  rh  r   r  r+  Zd0Zd1rY   rY   rZ   rd  V	  s    

rd  c                  G   s.   t jj|  }t d}t | t | |S )zuIn a testenv we end up with 0777 directories that look an alarming
    green colour with ls. Use umask to avoid that.?   )rK  rL  r   umaskmkdir)rL  r  maskrY   rY   rZ   r  h	  s
    


r  )r  )r]   r$   )r]   )N)	NNNNr   NNr&   F)T)r#  r  )T)T)T)|Z
__future__r   r   r   rK  r   r  r  rS   r  r  r   r   collectionsr   r   r   r	   Zdns.resolverr
   r  Zsamba.emulater   Zsamba.samdbr   r   r   Zsamba.dcerpcr   r   r   r   r   Zsamba.dcerpc.netlogonr   r   r   Zsamba.drs_utilsr   r`   Zsamba.credentialsr   r   r   Z
samba.authr   Z
samba.dsdbr   r   r   r   Zsamba.dcerpc.miscr   Zsambar    r!   Zsamba.compatr"   Zsamba.loggerr#   rL  r  r  rm  r  r   r   r   r  r  r  rQ   rr   r   r[   re   rp   r   rq   objectru   r   r   r   r?  rY  ry  r  r  r  r  r  r  rd  rc  r  r  r  r  r  r  r  r  r  r  r"  r$  r&  r   r,  r0  r  r2  r3  r5  r8  rB  r9  r:  rT  rj  rc  rd  r  rY   rY   rY   rZ   <module>   s  
    e (N
5	 a
b

@
$         
 
 

	
 
 
-  