a oeJ@sdZddlZddlZddlZddlZddlZddlZddlZddl Z ddl m Z ddl Tddl mZdadagZdaddlZeZd0d d Zd1d d Zd2ddZddZddZddZGdddZefddZddZddZddZd d!Z d"d#Z!d$d%Z"d&d'Z#d efd efd(e fde!fd)e"fde#ffZ$Gd*d+d+ej%Z&d,d-Z'e(d.kr|z e'Wne)yze*d/Yn0dS)3aA re-implementation of the MS DirectoryService samples related to services. * Adds and removes an ActiveDirectory "Service Connection Point", including managing the security on the object. * Creates and registers Service Principal Names. * Changes the username for a domain user. Some of these functions are likely to become move to a module - but there is also a little command-line-interface to try these functions out. For example: scp.py --account-name=domain\user --service-class=PythonScpTest \ --keyword=foo --keyword=bar --binding-string=bind_info \ ScpCreate SpnCreate SpnRegister would: * Attempt to delete a Service Connection Point for the service class 'PythonScpTest' * Attempt to create a Service Connection Point for that class, with 2 keywords and a binding string of 'bind_info' * Create a Service Principal Name for the service and register it to undo those changes, you could execute: scp.py --account-name=domain\user --service-class=PythonScpTest \ SpnCreate SpnUnregister ScpDelete which will: * Create a SPN * Unregister that SPN from the Active Directory. * Delete the Service Connection Point Executing with --test will create and remove one of everything. N)adsi)*)DispatchserviceConnectionPointAc Cs|p|}|sttj}|dur,ttj}td|tj} |pDg}dt t |ffdt t |ffdt t |fdt t |ffdt t |ffdt t |ffdt t |ffg} | d || } t d |t| } t|| | S) NLDAP://ZcnZ objectClasskeywordsZserviceDnsNameZserviceDnsNameTypeZserviceClassNameZserviceBindingInformationcn=zNew connection point is at %s)win32apiZGetComputerNameExwin32conZComputerNameDnsFullyQualifiedGetComputerObjectNameNameFullyQualifiedDNr ADsGetObjectIID_IDirectoryObjectZADS_ATTR_UPDATEZADSTYPE_CASE_IGNORE_STRINGZCreateDSObjectloggerinforAllowAccessToScpProperties) Zservice_binding_infoZservice_class_name account_namecontainer_namer Z object_classZ dns_name_typednZdns_namecompattrsnewr;C:\Program Files\Certbot\pkgs\win32comext\adsi\demos\scp.py ScpCreate?s@         rcCsR|durttj}td||td|tj}| d|t d|dS)Nz&Removing connection point '%s' from %srr z%Deleted service connection point '%s') r r r rrdebugrrrZDeleteDSObjectr)rrrrrr ScpDeleteys  rz&{28630eb8-41d5-11d1-a9c1-0000f80367c1}z&{b7b1311c-b82e-11d0-afee-0000f80367c1}c Cs|r |}n ttj}d}t||}|j}|D]@}ttj}t t B|_ ||_ t |_d|_t|_||_||q.||_t||||td|fdS)NZnTSecurityDescriptorrz'Set security on object for account '%s')r r r NameSamCompatiblegetattrZDiscretionaryAclrrZCLSID_AccessControlEntryZADS_RIGHT_DS_READ_PROPZADS_RIGHT_DS_WRITE_PROPZ AccessMaskZTrusteeZ!ADS_ACETYPE_ACCESS_ALLOWED_OBJECTZAceTypeZAceFlagsZADS_FLAG_OBJECT_TYPE_PRESENTZFlagsZ ObjectTypeZAddAcesetattrZSetInforr) Z accountSAMZ scpObjectZ schemaIDGUIDsZtrusteeZ attributesdZaclZsguidZacerrrrs&       rcCst|ttfvrt|ds&Jd|ttj}|ddd}|sRttj }t d|t j |tjtjBtjBd}t |d}t d t |||||dS) N__iter__z+spns must be a sequence of strings (got %r)\rrzSpnRegister using DN '%s')Z domainNameflagsZDomainControllerNamezDsWriteAccountSpn with spns %s)typestrhasattrr Z GetUserNameExr splitr r rrr win32securityZ DsGetDcNamedsconZDS_IS_FLAT_NAMEZDS_RETURN_DNS_NAMEZDS_DIRECTORY_SERVICE_REQUIREDZDsBindZDsWriteAccountSpnClose)Z serviceAcctDNspnsZ operationZsamNamerhandlerrr SpnRegisters2    r0cCs$d|}t|tj}||dS)Nr)rrZ IID_IADsUserZ SetPassword)Z username_dnZ new_passwordZ accountPathuserrrrUserChangePasswordsr2cGst|krt||dSN)verboseprint)levelmsgargsrrrlog sr9c@s eZdZdS) _NoDefaultN)__name__ __module__ __qualname__rrrrr:sr:cCs:|\}}t|||}|s.|tur.|d||s6|}|S)Nz4The '%s' option must be specified for this operation)r!r:error)poZopt_namedefaultparseroptionsretrrr _get_options  rDcCs|d}||dS)Nr)r>)r?whyrArrr _option_error srFcCs6tt|dt|dt|ddt|ddd}|a|jS)z!Create a Service Connection Pointbinding_string service_classaccount_name_samNr )r )rrD g_createdSCPdistinguishedName)r?Zscprrr do_ScpCreate%s  rLc Cs^t|d}z t|WnBtjyX}z(|dtjkr8tdd|WYd}~n d}~00|S)z!Delete a Service Connection PointrHrz@ScpDelete ignoring ERROR_DS_OBJ_NOT_FOUND for service-class '%s'N)rDrrr>winerrorZERROR_DS_OBJ_NOT_FOUNDr9)r?ZscZdetailsrrr do_ScpDelete2s  "rOc Cs^tdurt|dttjt|dtjt|dddd}|d}tdd||a t ||S)zCreate a Service Principal NameNz3ScpCreate must have been specified before SpnCreaterHportrrMzCreated SPN: %s) rJrFr+ZDsGetSpnr,ZDS_SPN_SERVICErDrKr9g_createdSPNLast g_createdSPNsappend)r?r.Zspnrrr do_SpnCreate>s    rTcCs*tst|dtt|ddtftjtS)z4Register a previously created Service Principal Namez(SpnCreate must appear before SpnRegisteraccount_name_dnN)rQrFr0rDr,ZDS_SPN_ADD_SPN_OPr?rrrdo_SpnRegisterUs  rWcCs*tst|dtt|ddtftjtS)z6Unregister a previously created Service Principal Namez*SpnCreate must appear before SpnUnregisterrUN)rQrFr0rDr,ZDS_SPN_DELETE_SPN_OPrVrrrdo_SpnUnregisterbs  rXcCstt|dt|ddS)z(Change the password for a specified userrUpasswordzPassword changed OK)r2rDrVrrrdo_UserChangePasswordnsrZZ SpnCreateZ SpnUnregisterc@seZdZddZdS) HelpFormattercCs|Sr3r)self descriptionrrrformat_descriptionsz HelpFormatter.format_descriptionN)r;r<r=r^rrrrr[~sr[c Csi}g}tD]<\}}dtj|jdd}|d||f|||<q tdd|d}tjd|t d}|j dd d d d d |j ddddd|j dddddf|j ddddd|j dddd|j ddddd|j dd d!d|j dd"d#d|j dd$d%d|j dd&d'd(d)d*|j dd+d,t t j d-|\}}||f} zt|j|_Wn"ttfy|d.Yn0zt|j} WnVttfyzttt |j} Wn$tttfy|d/Yn0Yn0z tj} Wntyt j} Yn0| | |jr6|jr6|d0|jrL|jd 8_|ja|jr|rj|d1d2}td d3||}|j sd4|_ td5d6|j |j!sd7|_!td5d8|j!|j"sd9|_"td5d:|j"|s|d;|D]"}||vr|d<|q|j#rptd5d=|j#t$%|j#t&j't&j(|_)td5d>|j)t$%|j#t&j't&j*|_+td5d?|j+|D],}||} | dur|d@|d} zRz&td5dA|| | }td dB||Wn&|j,rt-dCt./Yn0Wnt0jyT}zD|j1\}}}}|r&|d5}nd}|} |r@| dD|7} WYd}~n@d}~0t&jy}z|j1\}}}|} WYd}~n d}~00| rttd dE|| qtdS)FN z )subsequent_indentz %s: %sz commands: z%prog [options] command ...)usager] formatterz-vcountr4rz)increase the verbosity of status messages)actiondestr@helpz-qz--quiet store_truezDon't print any status messages)rdrfz-tz--testzGExecute a mini-test suite, providing defaults for most options and argsz--show-tracebacksz&Show the tracebacks for any exceptionsz--service-classzThe service class name to use)rfz--portrz)The port number to associate with the SPN)r@rfz--binding-stringz*The binding string to use for SCP creationz--account-namez0The account name to use (default is LocalSystem)z --passwordzThe password to set.z --keywordrSr z[A keyword to add to the SCP. May be specified multiple times)rdrerfz --log-levelz`The log-level to use - may be a number or a logging module constant)rfr@z--port must be numericzInvalid --log-level valuez#Can't specify --quiet and --verbosezCan't specify args with --testzAScpDelete ScpCreate SpnCreate SpnRegister SpnUnregister ScpDeletez!--test - pretending args are: %sZ PythonScpTestrMz--test: --service-class=%szPython Poweredz--test: --keyword=%sztest binding stringz--test: --binding-string=%sz4No command specified (use --help for valid commands)z4Invalid command '%s' (use --help for valid commands)zTranslating account name '%s'zNameSamCompatible is '%s'zNameFullyQualifiedDNis '%s'zInvalid command '%s'zExecuting '%s'...z%s: %sz/--show-tracebacks specified - dumping exceptionz zCommand '%s' failed: %s)2handlersjointextwrapwrap__doc__rSloweroptparseZ OptionParserr[Z add_optionr(loggingZWARNING parse_argsintrP TypeError ValueErrorr> log_levelr!upperAttributeErrorrZsetLevelZ getLoggerquietr4testr9r*rHr rGrr+Z TranslateNamer Z NameUnknownr rIrrUZshow_tracebacksr5 traceback print_excrr8)Z_handlers_dictZ arg_descsargfuncZ this_descr]rArBr8r?ruslZhandlererr_msgresultZxxx_todo_changemehrZdescexcZargerrZ extra_descZxxx_todo_changeme1r7rrrmains                   r__main__z*** Interrupted)NNNrrNN)N)r)+rmrorkrzZ ntsecurityconr,r r r+rNZ win32com.adsirZwin32com.adsi.adsiconZwin32com.clientrr4rJrRrQrprrrrr0r2r9r:rDrFrLrOrTrWrXrZriZIndentedHelpFormatterr[rr;KeyboardInterruptr5rrrrsn$    :  D)       /