/// <summary> /// The NetrServerPasswordSet2 method Supported in windows_2000_server, /// windows_xp, windows_server_2003, windows_vista, windows_server_2008, /// windows_7, and windows_server_7. allows the client /// to set a new clear text password for an account used /// by the domain controller (as specified in section ) /// for setting up the secure channel from the client. A /// domain member uses this function to periodically change /// its machine account password. A PDC uses this function /// to periodically change the trust password for all directly /// trusted domains. By default, the period is 30 days /// in windows_2000_server, windows_xp, windows_server_2003, /// windows_vista, windows_server_2008, windows_7, and /// windows_server_7. Opnum: 30 /// </summary> /// <param name="PrimaryName"> /// The custom RPC binding handle, as specified in section /// . /// </param> /// <param name="AccountName"> /// The null-terminated Unicode string that contains the /// name of the account whose password is being changed. In /// windows, all machine account names are the name of /// the machine with a $ (dollar sign) appended. /// </param> /// <param name="SecureChannelType"> /// An enumerated value that describes the secure channel /// to be used for authentication, as specified in section /// . /// </param> /// <param name="ComputerName"> /// The null-terminated Unicode string that contains the /// NetBIOS name of the computer making the request. /// </param> /// <param name="Authenticator"> /// A pointer to a NETLOGON_AUTHENTICATOR structure, as /// specified in section , that contains the encrypted /// logon credential and a time stamp. /// </param> /// <param name="ReturnAuthenticator"> /// A pointer to a NETLOGON_AUTHENTICATOR structure, as /// specified in section , that contains the server return /// authenticator. /// </param> /// <param name="ClearNewPassword"> /// A pointer to an NL_TRUST_PASSWORD structure, as specified /// in section , that contains the new password encrypted /// as specified in Calling NetrServerPasswordSet2. /// </param> public NtStatus NetrServerPasswordSet2( string PrimaryName, string AccountName, _NETLOGON_SECURE_CHANNEL_TYPE SecureChannelType, string ComputerName, _NETLOGON_AUTHENTICATOR? Authenticator, out _NETLOGON_AUTHENTICATOR? ReturnAuthenticator, _NL_TRUST_PASSWORD? ClearNewPassword) { const ushort opnum = 30; byte[] requestStub; byte[] responseStub; Int3264[] paramList; int retVal; SafeIntPtr pPrimaryName = Marshal.StringToHGlobalUni(PrimaryName); SafeIntPtr pAccountName = Marshal.StringToHGlobalUni(AccountName); SafeIntPtr pComputerName = Marshal.StringToHGlobalUni(ComputerName); SafeIntPtr pAuthenticator = TypeMarshal.ToIntPtr(Authenticator); SafeIntPtr pClearNewPassword = TypeMarshal.ToIntPtr(ClearNewPassword); paramList = new Int3264[] { pPrimaryName, pAccountName, (uint)SecureChannelType, pComputerName, pAuthenticator, IntPtr.Zero, pClearNewPassword, 0 // retVal }; requestStub = RpceStubEncoder.ToBytes( RpceStubHelper.GetPlatform(), NrpcRpcStubFormatString.TypeFormatString, new RpceStubExprEval[] { new RpceStubExprEval(logon__NETLOGON_DELTA_USERExprEval_0000) }, NrpcRpcStubFormatString.ProcFormatString, NrpcRpcStubFormatString.ProcFormatStringOffsetTable[opnum], true, paramList); rpceClientTransport.Call(opnum, requestStub, rpceTimeout, out responseStub); using (RpceInt3264Collection outParamList = RpceStubDecoder.ToParamList( RpceStubHelper.GetPlatform(), NrpcRpcStubFormatString.TypeFormatString, new RpceStubExprEval[] { new RpceStubExprEval(logon__NETLOGON_DELTA_USERExprEval_0000) }, NrpcRpcStubFormatString.ProcFormatString, NrpcRpcStubFormatString.ProcFormatStringOffsetTable[opnum], true, responseStub, paramList)) { IntPtr pReturnAuthenticator = outParamList[5]; ReturnAuthenticator = TypeMarshal.ToNullableStruct<_NETLOGON_AUTHENTICATOR>(pReturnAuthenticator); retVal = outParamList[7].ToInt32(); } pPrimaryName.Dispose(); pAccountName.Dispose(); pComputerName.Dispose(); pAuthenticator.Dispose(); pClearNewPassword.Dispose(); return (NtStatus)retVal; }
/// <summary> /// Encrypt a NL_TRUST_PASSWORD structure. /// </summary> /// <param name="nlTrustPassword"> /// A NL_TRUST_PASSWORD structure which contains data to be encrypted. /// </param> /// <returns>Encrypted NL_TRUST_PASSWORD.</returns> /// <exception cref="ArgumentException"> /// Thrown when nlTrustPassword is invalid. /// </exception> /// <exception cref="InvalidOperationException"> /// Thrown when the method is called before establishing a NRPC secure channel. /// Thrown when neither AES nor RC4 is negotiated. /// </exception> public _NL_TRUST_PASSWORD EncryptNlTrustPassword(_NL_TRUST_PASSWORD nlTrustPassword) { if (nlTrustPassword.Buffer == null) { throw new ArgumentException("nlTrustPassword is invalid.", "nlTrustPassword"); } ValidateSecureChannelExists(); //Encrypt the ClearNewPassword parameter using the RC4 algorithm //and the session key established as the encryption key. using (SafeIntPtr ptr = TypeMarshal.ToIntPtr(nlTrustPassword)) { byte[] buf = new byte[ nlTrustPassword.Buffer.Length * sizeof(ushort) + Marshal.SizeOf(nlTrustPassword.Length)]; Marshal.Copy(ptr, buf, 0, buf.Length); buf = NrpcUtility.EncryptBuffer(IsAesOrRc4Negotiated(), context.SessionKey, buf); Marshal.Copy(buf, 0, ptr, buf.Length); return TypeMarshal.ToStruct<_NL_TRUST_PASSWORD>(ptr); } }
/// <summary> /// The NetrServerPasswordSet2 method Supported in windows_2000_server, /// windows_xp, windows_server_2003, windows_vista, windows_server_2008, /// windows_7, and windows_server_7. allows the client /// to set a new clear text password for an account used /// by the domain controller /// for setting up the secure channel from the client. A /// domain member uses this function to periodically change /// its machine account password. A PDC uses this function /// to periodically change the trust password for all directly /// trusted domains. By default, the period is 30 days /// in windows_2000_server, windows_xp, windows_server_2003, /// windows_vista, windows_server_2008, windows_7, and /// windows_server_7. Opnum: 30 /// </summary> /// <param name="primaryName"> /// The custom RPC binding handle. /// </param> /// <param name="accountName"> /// The null-terminated Unicode string that contains the /// name of the account whose password is being changed. In /// windows, all machine account names are the name of /// the machine with a $ (dollar sign) appended. /// </param> /// <param name="secureChannelType"> /// An enumerated value that describes the secure channel /// to be used for authentication. /// </param> /// <param name="computerName"> /// The null-terminated Unicode string that contains the /// NetBIOS name of the computer making the request. /// </param> /// <param name="authenticator"> /// A pointer to a NETLOGON_AUTHENTICATOR structure, /// that contains the encrypted /// logon credential and a time stamp. /// </param> /// <param name="returnAuthenticator"> /// A pointer to a NETLOGON_AUTHENTICATOR structure, /// that contains the server return /// authenticator. /// </param> /// <param name="clearNewPassword"> /// A pointer to an NL_TRUST_PASSWORD structure, /// that contains the new password encrypted /// as specified in Calling NetrServerPasswordSet2. /// </param> /// <returns> /// The method returns 0x00000000 on success; /// otherwise, it returns a nonzero error code. /// </returns> public NtStatus NetrServerPasswordSet2( string primaryName, string accountName, _NETLOGON_SECURE_CHANNEL_TYPE secureChannelType, string computerName, _NETLOGON_AUTHENTICATOR? authenticator, out _NETLOGON_AUTHENTICATOR? returnAuthenticator, _NL_TRUST_PASSWORD? clearNewPassword) { NtStatus status = rpc.NetrServerPasswordSet2( primaryName, accountName, secureChannelType, computerName, authenticator, out returnAuthenticator, clearNewPassword); context.ConnectionStatus = status; return status; }
/// <summary> /// Create an instance of NL_TRUST_PASSWORD structure. /// The data is not encrypted, the caller should call /// EncryptNlTrustPassword to encrypt it. /// </summary> /// <param name="password">The clear text password. /// </param> /// <param name="isInterdomainAccount"> /// If the password is for an interdomain account, /// the TrustPasswordVersion in context will be added to /// NL_TRUST_PASSWORD structure and updated accordingly. /// For any other type of account, TrustPasswordVersion is not used. /// </param> /// <returns>Created but not-yet-encrypted NL_TRUST_PASSWORD structure.</returns> /// <exception cref="ArgumentNullException"> /// Thrown when password is null. /// </exception> /// <exception cref="ArgumentException"> /// Thrown when password length exceeds the limit. /// </exception> public _NL_TRUST_PASSWORD CreateNlTrustPassword( string password, bool isInterdomainAccount) { if (password == null) { throw new ArgumentNullException("password"); } _NL_TRUST_PASSWORD nlTrustPassword = new _NL_TRUST_PASSWORD(); //The ClearNewPassword parameter is constructed as follows, //assuming a WCHAR-represented password of length X bytes. byte[] passwordBuffer = Encoding.Unicode.GetBytes(password); int X = passwordBuffer.Length; if (X > 512) { throw new ArgumentException("password length exceeds the limit.", "password"); } byte[] buffer; if (isInterdomainAccount) { //If the password is for an interdomain account: //An NL_PASSWORD_VERSION structure, as specified in section 2.2.1.3.8, //is prepared. The PasswordVersionNumber field of the structure is set to //the value of the TrustPasswordVersion variable corresponding to //the password being set. The first trust password generated has //TrustPasswordVersion equal to one. Each time a new trust password //is generated, its TrustPasswordVersion is computed by adding one //to the value of TrustPasswordVersion of the previous password. //The NL_PASSWORD_VERSION structure is copied into ClearNewPassword.Buffer //starting at byte offset (512 - X - size of (NL_PASSWORD_VERSION)). _NL_PASSWORD_VERSION nlPasswordVersion = new _NL_PASSWORD_VERSION(); nlPasswordVersion.ReservedField = ReservedField_Values.V1; nlPasswordVersion.PasswordVersionNumber = context.TrustPasswordVersion; nlPasswordVersion.PasswordVersionPresent = PasswordVersionPresent_Values.V1; byte[] nlPasswordVersionBuf = TypeMarshal.ToBytes(nlPasswordVersion); if ((X + nlPasswordVersionBuf.Length) > 512) { throw new ArgumentException("password length exceeds the limit.", "password"); } //The password is copied into the Buffer field of ClearNewPassword, //which is treated as an array of bytes, starting at byte offset (512 - X). //The first (512 - X) - size of (NL_PASSWORD_VERSION) bytes of //ClearNewPassword.Buffer are filled with randomly generated data. buffer = ArrayUtility.ConcatenateArrays( NrpcUtility.GenerateNonce(512 - X - nlPasswordVersionBuf.Length), nlPasswordVersionBuf, passwordBuffer); context.TrustPasswordVersion += 1; } else { //If the password is not for an interdomain account: buffer = ArrayUtility.ConcatenateArrays( NrpcUtility.GenerateNonce(512 - X), passwordBuffer); } nlTrustPassword.Buffer = new ushort[256]; Buffer.BlockCopy(buffer, 0, nlTrustPassword.Buffer, 0, 512); //ClearNewPassword.Length is set to X. nlTrustPassword.Length = (uint)X; return nlTrustPassword; }