/// <summary>
        ///  The NetrLogonSamLogoff method handles logoff requests
        ///  for the SAM accounts. Opnum: 3
        /// </summary>
        /// <param name="logonServer">
        ///  The custom RPC binding handle.
        /// </param>
        /// <param name="computerName">
        ///  The Unicode string that contains the NetBIOS name of
        ///  the client computer calling this method.
        /// </param>
        /// <param name="authenticator">
        ///  A pointer to a NETLOGON_AUTHENTICATOR structure,
        ///  that contains the client authenticator.
        /// </param>
        /// <param name="returnAuthenticator">
        ///  A pointer to a NETLOGON_AUTHENTICATOR structure,
        ///  that contains the server return
        ///  authenticator.
        /// </param>
        /// <param name="logonLevel">
        ///  A NETLOGON_LOGON_INFO_CLASS structure,
        ///  that identifies the type of logon information
        ///  in the LogonInformation union.
        /// </param>
        /// <param name="logonInformation">
        ///  A pointer to a NETLOGON_LEVEL structure,
        ///  that describes the logon information.
        /// </param>
        /// <param name="isLogonInfoNull">
        ///  Indicate if the logonInformation field is NULL.
        ///  </param>
        /// <returns>
        /// The method returns 0x00000000 on success;
        /// otherwise, it returns a nonzero error code.
        /// </returns>
        public NtStatus NetrLogonSamLogoff(
            string logonServer,
            string computerName,
            _NETLOGON_AUTHENTICATOR?authenticator,
            ref _NETLOGON_AUTHENTICATOR?returnAuthenticator,
            _NETLOGON_LOGON_INFO_CLASS logonLevel,
            _NETLOGON_LEVEL?logonInformation,
            bool isLogonInfoNull)
        {
            NtStatus status = this.customRpc.NetrLogonSamLogoff(
                logonServer,
                computerName,
                authenticator,
                ref returnAuthenticator,
                logonLevel,
                logonInformation,
                isLogonInfoNull);

            this.context.ConnectionStatus = status;
            return(status);
        }
        /// <summary>
        ///  The NetrLogonSamLogonWithFlags method Supported in windows_xpwindows_server_2003,
        ///  windows_vista, windows_server_2008, windows_7, and
        ///  windows_server_7. handles logon requests for the SAM
        ///  accounts. Opnum: 45 
        /// </summary>
        /// <param name="LogonServer">
        ///  The custom RPC binding handle, as specified in section
        ///  .
        /// </param>
        /// <param name="ComputerName">
        ///  The Unicode string that contains the NetBIOS name of
        ///  the client computer calling this method.
        /// </param>
        /// <param name="Authenticator">
        ///  A pointer to a NETLOGON_AUTHENTICATOR structure, as
        ///  specified in section , that contains the client authenticator.
        /// </param>
        /// <param name="ReturnAuthenticator">
        ///  A pointer to a NETLOGON_AUTHENTICATOR structure, as
        ///  specified in section , that contains the server return
        ///  authenticator.
        /// </param>
        /// <param name="LogonLevel">
        ///  A NETLOGON_LOGON_INFO_CLASS structure, as specified
        ///  in section , that specifies the type of logon information
        ///  passed in the LogonInformation parameter.
        /// </param>
        /// <param name="LogonInformation">
        ///  A pointer to a NETLOGON_LEVEL structure, as specified
        ///  in section , that describes the logon request information.
        /// </param>
        /// <param name="ValidationLevel">
        ///  A NETLOGON_VALIDATION_INFO_CLASS enumerated type, as
        ///  specified in section , that contains the validation
        ///  level requested by the client.
        /// </param>
        /// <param name="ValidationInformation">
        ///  A pointer to a NETLOGON_VALIDATION structure, as specified
        ///  in section , that describes the user validation information
        ///  returned to the client. The type of the NETLOGON_VALIDATION
        ///  used is determined by the value of the ValidationLevel
        ///  parameter.
        /// </param>
        /// <param name="Authoritative">
        ///  A pointer to a char value representing a Boolean condition.
        ///  FALSE is indicated by the value 0x00; TRUE SHOULD be
        ///  indicated by the value 0x01 and MAY also be indicated
        ///  by any nonzero value. Windows uses the value of 0x01
        ///  as the representation of TRUE and 0x00 for FALSE. This
        ///  Boolean value indicates whether the validation information
        ///  is final. This field is necessary because the request
        ///  might be forwarded through multiple servers. A value
        ///  of TRUE indicates that the validation information is
        ///  final and MUST remain unchanged.
        /// </param>
        /// <param name="ExtraFlags">
        ///  A pointer to a set of bit flags that specify delivery
        ///  settings. A flag is TRUE (or set) if its value is equal
        ///  to 1. The value is constructed from zero or more bit
        ///  flags from the following table.
        /// </param>
        public NtStatus NetrLogonSamLogonWithFlags(
            string LogonServer,
            string ComputerName,
            _NETLOGON_AUTHENTICATOR? Authenticator,
            ref _NETLOGON_AUTHENTICATOR? ReturnAuthenticator,
            _NETLOGON_LOGON_INFO_CLASS LogonLevel,
            _NETLOGON_LEVEL? LogonInformation,
            _NETLOGON_VALIDATION_INFO_CLASS ValidationLevel,
            out _NETLOGON_VALIDATION? ValidationInformation,
            out byte? Authoritative,
            ref uint? ExtraFlags)
        {
            const ushort opnum = 45;

            byte[] requestStub;
            byte[] responseStub;
            Int3264[] paramList;
            int retVal;

            SafeIntPtr pLogonServer = Marshal.StringToHGlobalUni(LogonServer);
            SafeIntPtr pComputerName = Marshal.StringToHGlobalUni(ComputerName);
            SafeIntPtr pAuthenticator = TypeMarshal.ToIntPtr(Authenticator);
            SafeIntPtr pReturnAuthenticatorIn = TypeMarshal.ToIntPtr(ReturnAuthenticator);
            SafeIntPtr pLogonInformation = TypeMarshal.ToIntPtr(LogonInformation, LogonLevel, null, null);
            SafeIntPtr pExtraFlags = TypeMarshal.ToIntPtr(ExtraFlags);

            paramList = new Int3264[] {
                pLogonServer,
                pComputerName,
                pAuthenticator,
                pReturnAuthenticatorIn,
                (uint)LogonLevel,
                pLogonInformation,
                (uint)ValidationLevel,
                IntPtr.Zero,
                IntPtr.Zero,
                pExtraFlags,
                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 pReturnAuthenticatorOut = outParamList[3];
                ReturnAuthenticator = TypeMarshal.ToNullableStruct<_NETLOGON_AUTHENTICATOR>(pReturnAuthenticatorOut);

                IntPtr pValidationInformation = outParamList[7];
                ValidationInformation = TypeMarshal.ToNullableStruct<_NETLOGON_VALIDATION>(
                    pValidationInformation,
                    ValidationLevel,
                    null,
                    null);

                Authoritative = TypeMarshal.ToNullableStruct<byte>(outParamList[8]);

                ExtraFlags = TypeMarshal.ToNullableStruct<uint>(outParamList[9]);

                retVal = outParamList[10].ToInt32();
            }

            pLogonServer.Dispose();
            pComputerName.Dispose();
            pAuthenticator.Dispose();
            pReturnAuthenticatorIn.Dispose();
            pLogonInformation.Dispose();
            pExtraFlags.Dispose();

            return (NtStatus)retVal;
        }
Beispiel #3
0
        /// <summary>
        /// Send KERB_VERIFY_PAC_REQUEST message to DC through generic pass-through mechanism
        /// </summary>
        /// <param name="serverSignature">Server Signature in the privilege attribute certificate (PAC)</param>
        /// <param name="kdcSignature">Key Distribution Center (KDC) Signature in the PAC</param>
        /// <returns></returns>
        public Status GenerateKerberosValidationRequest(
            PAC_SIGNATURE_DATA serverSignature,
            PAC_SIGNATURE_DATA kdcSignature)
        {
            _NETLOGON_LOGON_INFO_CLASS      logonLevel      = _NETLOGON_LOGON_INFO_CLASS.NetlogonGenericInformation;
            _NETLOGON_VALIDATION_INFO_CLASS validationLevel = _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationGenericInfo2;

            //Get Kerberos Request
            KERB_VERIFY_PAC_REQUEST kerberosReq = ApdsUtility.CreateKerbVerifyPacRequest(serverSignature, kdcSignature);

            //Create digest validation logon info
            _NETLOGON_LEVEL netlogonLevel = ApdsUtility.CreatePacLogonInfo(
                NrpcParameterControlFlags.AllowLogonWithComputerAccount,
                PrimaryDomainDnsName,
                DomainAdministratorName,
                PDCNetbiosName,
                kerberosReq);

            //Create Secure Channel
            EstablishSecureChannel();

            //Client calls EncryptNetlogonLevel
            _NETLOGON_LEVEL encryptedLogonLevel = nrpcClient.EncryptNetlogonLevel(
                (_NETLOGON_LOGON_INFO_CLASS)logonLevel,
                netlogonLevel);

            //Client calls NetrLogonSamLogonEx
            _NETLOGON_VALIDATION?validationInfomation;
            byte?authoritative;
            NrpcNetrLogonSamLogonExtraFlags?extraFlags = NrpcNetrLogonSamLogonExtraFlags.None;

            result = nrpcClient.NetrLogonSamLogonEx(
                nrpcClient.Handle,
                sutComputerName,
                clientComputerName,
                logonLevel,
                encryptedLogonLevel,
                validationLevel,
                out validationInfomation,
                out authoritative,
                ref extraFlags);

            // Whether this method use pass-through mechanism or not.
            bool isPassThroughMethod = false;

            //Kerberos PAC validation SHOULD use the generic pass-through mechanism ([MS-NRPC] section 3.2.4.1).
            //For generic pass-through, the LogonLevel is 4(NetlogonGenericInformation) as defined in [MS-NRPC] section 3.2.4.1.
            //So when the LogonLevel is  4, we can say that NRPC pass-through authentication method is used.
            if ((int)logonLevel == 4)
            {
                isPassThroughMethod = true;
            }
            Site.CaptureRequirementIfIsTrue(
                isPassThroughMethod,
                5,
                @"For domain support, authentication protocols MUST use an NRPC pass-through authentication 
                ([MS-NRPC] section 3.2) method with parameters determined by the authentication protocol being 
                used[to return the response structures to member server].");
            Site.CaptureRequirementIfAreEqual <int>(
                5,
                (int)validationLevel,
                402,
                @"The encoded data SHOULD be sent by using the generic pass-through mechanism ([MS-NRPC] section 3.2.4.1).");

            if (result == NtStatus.STATUS_SUCCESS)
            {
                Site.CaptureRequirementIfIsNull(validationInfomation.Value.ValidationGeneric2[0].ValidationData, 403,
                                                @"If the checksum is verified, the DC MUST return STATUS_SUCCESS. There is no return message.");
            }
            return((Status)result);
        }
 /// <summary>
 ///  Decodes the request stub, and fills the fields of the class
 /// </summary>
 /// <param name="sessionContext">The session context of the request received</param>
 /// <param name="requestStub">The request stub got from RPCE layer</param>
 internal override void Decode(NrpcServerSessionContext sessionContext, byte[] requestStub)
 {
     using (RpceInt3264Collection outParamList = RpceStubDecoder.ToParamList(
       RpceStubHelper.GetPlatform(),
         NrpcRpcStubFormatString.TypeFormatString,
         new RpceStubExprEval[] {
             new RpceStubExprEval(NrpcRpcAdapter.logon__NETLOGON_DELTA_USERExprEval_0000) },
         NrpcRpcStubFormatString.ProcFormatString,
         NrpcRpcStubFormatString.ProcFormatStringOffsetTable[(int)Opnum],
         false,
         requestStub))
     {
         LogonServer = Marshal.PtrToStringUni(outParamList[0]);
         ComputerName = Marshal.PtrToStringUni(outParamList[1]);
         Authenticator = TypeMarshal.ToNullableStruct<_NETLOGON_AUTHENTICATOR>(outParamList[2]);
         ReturnAuthenticator = TypeMarshal.ToNullableStruct<_NETLOGON_AUTHENTICATOR>(outParamList[3]);
         LogonLevel = (_NETLOGON_LOGON_INFO_CLASS)outParamList[4].ToInt32();
         LogonInformation = TypeMarshal.ToNullableStruct<_NETLOGON_LEVEL>(outParamList[5], LogonLevel, null, null);
         ValidationLevel = (_NETLOGON_VALIDATION_INFO_CLASS)outParamList[6].ToInt32();
         ExtraFlags = TypeMarshal.ToNullableStruct<uint>(outParamList[9]);
     }
 }
Beispiel #5
0
        /// <summary>
        /// Send NTLM request message to DC for validation.
        /// </summary>
        /// <param name="logonLevel">Indicates the logon level.</param>
        /// <param name="accountInfo">Indicates whether this account is valid in DC validation.</param>
        /// <param name="isAccessCheckSuccess">Indicates whether the access checked success.</param>
        /// <param name="validationLevel">Indicates the validation level.</param>
        /// <returns>Indicates the result status of DC response.</returns>
        public Status NTLMLogon(
            _NETLOGON_LOGON_INFO_CLASS logonLevel,
            AccountInformation accountInfo,
            Boolean isAccessCheckSuccess,
            _NETLOGON_VALIDATION_INFO_CLASS validationLevel)
        {
            //Compute the password
            GenerateCurrentCredentials(accountInfo);

            //Create Secure Channel
            EstablishSecureChannel();

            _NETLOGON_LEVEL netLogonLevel = new _NETLOGON_LEVEL();

            if (logonLevel == _NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation)
            {
                //Fill InteractiveInfo
                netLogonLevel = ApdsUtility.CreateNlmpInteractiveLogonInfo(
                    NrpcParameterControlFlags.AllowLogonWithComputerAccount,
                    sutTrustDomainName,
                    currentUserName,
                    currentPassword,
                    sutComputerName);
            }
            else if (logonLevel == _NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkInformation)
            {
                //Fill Netlogon_Network_Info
                if (accountInfo == AccountInformation.ManagedServiceAccount)
                {
                    netLogonLevel = nrpcClient.CreateNetlogonLevel(
                        _NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkInformation,
                        NrpcParameterControlFlags.AllowLogonWithComputerAccount,
                        sutDomainName, // managed service account is created in the local domain
                        currentUserName,
                        currentPassword);
                }
                else
                {
                    netLogonLevel = nrpcClient.CreateNetlogonLevel(
                        _NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkInformation,
                        NrpcParameterControlFlags.AllowLogonWithComputerAccount,
                        sutTrustDomainName,
                        currentUserName,
                        currentPassword);
                }
            }

            _NETLOGON_LEVEL encryptedLogonLevel = nrpcClient.EncryptNetlogonLevel(
                logonLevel,
                netLogonLevel);

            byte?authoritative;
            _NETLOGON_VALIDATION?           validationInformation = new _NETLOGON_VALIDATION();
            NrpcNetrLogonSamLogonExtraFlags?extraFlags            = NrpcNetrLogonSamLogonExtraFlags.None;

            result = nrpcClient.NetrLogonSamLogonEx(
                nrpcClient.Handle,
                sutComputerName,
                clientComputerName,
                logonLevel,
                encryptedLogonLevel,
                validationLevel,
                out validationInformation,
                out authoritative,
                ref extraFlags);

            // Whether this method use pass-through mechanism or not.
            bool isPassThroughMethod = false;

            //
            //For NTLM pass-through, the LogonLevel is 1(NetlogonInteractiveInformation) or 2(NetlogonNetworkInformation)
            //based on Interactive Logono and Network Logon,as defined in [MS-APDS] section 3.1.5.1 and section 3.1.5.2.
            //So when the LogonLevel is 1 or 2, we can say that NRPC pass-through authentication method is used.
            //
            if ((int)logonLevel == 1 || (int)logonLevel == 2)
            {
                isPassThroughMethod = true;
            }

            //
            //Verify MS-APDS requirment:MS-APDS_R5
            //
            Site.CaptureRequirementIfIsTrue(
                isPassThroughMethod,
                5,
                @"For domain support, authentication protocols MUST use an NRPC pass-through authentication 
                ([MS-NRPC] section 3.2) method with parameters determined by the authentication protocol being 
                used[to return the response structures to member server].");

            //
            //Verify MS-APDS requirment:MS-APDS_R118
            //if isPassThroughMethod is true, this requirement can be verified.
            //
            Site.CaptureRequirementIfIsTrue(
                isPassThroughMethod,
                118,
                @"NT LAN Manager (NTLM) interactive logon and network logon MUST receive the authentication 
                response sequence by contacting the DC using an NRPC pass-through authentication method .");

            if (result == NtStatus.STATUS_SUCCESS)
            {
                if (validationLevel == _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4)
                {
                    VerifyNTLMDataStructure(validationLevel, logonLevel);

                    VerifyMessageSyntxNTLMValidV4Resp(
                        validationInformation.Value.ValidationSam4[0].UserSessionKey.data[0].data,
                        validationInformation.Value.ValidationSam4[0].EffectiveName.ToString());
                }
                else if (validationLevel == _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo2)
                {
                    VerifyNTLMDataStructure(validationLevel, logonLevel);
                }
                else if (validationLevel == _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo)
                {
                    VerifyNTLMDataStructure(validationLevel, logonLevel);
                }
            }

            return((Status)result);
        }
Beispiel #6
0
        /// <summary>
        /// Send Digest request message to DC, and validate the credentials.
        /// </summary>
        /// <param name="isValidationSuccess">Indicates whether the validation from server will be success.</param>
        /// <param name="digestType">Indicates the DigestType field of the request.</param>
        /// <param name="algType">Indicates the AlgType field of the request.</param>
        /// <param name="ignoredFields">It indicates the fields that should be ignored by DC in DIGEST_VALIDATION_REQ.</param>
        /// <returns>Indicates the result status of DC response.</returns>
        public Status GenerateDigestRequest(
            Boolean isValidationSuccess,
            AccountInformation accountInfo,
            DigestType_Values digestType,
            AlgType_Values algType,
            IgnoredFields ignoredFields)
        {
            DIGEST_VALIDATION_REQ           digestReq;
            _NETLOGON_LOGON_INFO_CLASS      logonLevel      = _NETLOGON_LOGON_INFO_CLASS.NetlogonGenericInformation;
            _NETLOGON_VALIDATION_INFO_CLASS validationLevel = _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationGenericInfo2;

            //Compute the password
            GenerateCurrentCredentials(accountInfo);

            //Get Digest Request
            GetDigestRequest(digestType, algType, ignoredFields, out digestReq);

            //Create digest validation logon info
            _NETLOGON_LEVEL netlogonLevel = ApdsUtility.CreateDpspLogonInfo(
                NrpcParameterControlFlags.AllowLogonWithComputerAccount,
                digestReq);

            //Create Secure Channel
            EstablishSecureChannel();

            //Client calls EncryptNetlogonLevel
            _NETLOGON_LEVEL encryptedLogonLevel = nrpcClient.EncryptNetlogonLevel(
                (_NETLOGON_LOGON_INFO_CLASS)logonLevel,
                netlogonLevel);

            //Client calls NetrLogonSamLogonEx
            _NETLOGON_VALIDATION?validationInfomation;
            byte?authoritative;
            NrpcNetrLogonSamLogonExtraFlags?extraFlags = NrpcNetrLogonSamLogonExtraFlags.None;

            result = nrpcClient.NetrLogonSamLogonEx(
                nrpcClient.Handle,
                sutComputerName,
                clientComputerName,
                logonLevel,
                encryptedLogonLevel,
                validationLevel,
                out validationInfomation,
                out authoritative,
                ref extraFlags);

            // Whether this method use pass-through mechanism or not.
            bool isPassThroughMethod = false;

            //
            //The Digest validation protocol SHOULD use the generic pass-through mechanism.
            //For generic pass-through, the LogonLevel is 4(NetlogonGenericInformation) as defined in [MS-NRPC] section 3.2.4.1.
            //So when the LogonLevel is  4, we can say that NRPC pass-through authentication method is used.
            //
            if ((int)logonLevel == 4)
            {
                isPassThroughMethod = true;
            }
            //
            //Verify MS-APDS requirment:MS-APDS_R5
            //
            Site.CaptureRequirementIfIsTrue(
                isPassThroughMethod,
                5,
                @"For domain support, authentication protocols MUST use an NRPC pass-through authentication 
                ([MS-NRPC] section 3.2) method with parameters determined by the authentication protocol being 
                used[to return the response structures to member server].");

            //
            //Verify MS-APDS requirment:MS-APDS_R15
            //
            Site.CaptureRequirementIfAreEqual <int>(
                5,
                (int)validationLevel,
                15,
                @"Digest response messages MUST be encoded as opaque blobs and transported 
                by the generic pass-through capability of Netlogon.");

            //
            //Configured in PTFConfig file,default SHOULD to true and MAY to false.
            //
            string isR169Implemented = "true";

            //
            //Check OS version
            //
            if (isWindows)
            {
                //
                //Verify MS-APDS requirment:MS-APDS_R100169
                //
                Site.CaptureRequirementIfAreEqual <int>(
                    5,
                    (int)validationLevel,
                    100169,
                    @"In Windows, the Digest validation protocol uses the generic pass-through mechanism.");

                if (null == isR169Implemented)
                {
                    Site.Properties.Add("R169Implemented", Boolean.TrueString);
                    isR169Implemented = Boolean.TrueString;
                }
            }
            if (null != isR169Implemented)
            {
                bool implSigns   = Boolean.Parse(isR169Implemented);
                bool isSatisfied = ((int)_NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationGenericInfo2 == 5);
                //
                //Verify MS-APDS requirment:MS-APDS_R169
                //
                Site.CaptureRequirementIfAreEqual <Boolean>(
                    implSigns,
                    isSatisfied,
                    169,
                    string.Format(@"The Digest validation protocol SHOULD use the generic pass-through mechanism. 
                   This requirement is {0} implemented.", implSigns ? "" : "not"));
            }

            byte[] buf;
            bool   isDigestResStructure = true;
            DIGEST_VALIDATION_RESP digestValidationResponse = new DIGEST_VALIDATION_RESP();

            // Judge whether the digest response is exist, validationData is response point.
            // if validationData equals 0, no response return from NRPC.
            if (validationInfomation.Value.ValidationGeneric2 == null)
            {
                isDigestResStructure = false;
            }
            else
            {
                // decrypt validation info
                buf = NrpcUtility.DecryptBuffer(
                    (nrpcClient.Context.NegotiateFlags & NrpcNegotiateFlags.SupportsAESAndSHA2) == NrpcNegotiateFlags.SupportsAESAndSHA2,
                    nrpcClient.Context.SessionKey,
                    validationInfomation.Value.ValidationGeneric2[0].ValidationData);

                _NETLOGON_VALIDATION decryptValidationInfo = new _NETLOGON_VALIDATION();
                decryptValidationInfo.ValidationGeneric2 = new _NETLOGON_VALIDATION_GENERIC_INFO2[1];
                decryptValidationInfo.ValidationGeneric2[0].ValidationData = buf;

                digestValidationResponse =
                    ApdsUtility.ConvertDataToDigestValidationResponse(decryptValidationInfo);

                VerifyMessageSyntaxDigestValidCredential(digestValidationResponse, validationLevel, (uint)buf.Length);
            }

            if (result != NtStatus.STATUS_SUCCESS)
            {
                //
                //Verify MS-APDS requirment:MS-APDS_R292
                //
                Site.CaptureRequirementIfIsFalse(
                    isDigestResStructure,
                    292,
                    "[If unsuccessful]It[DC] MUST NOT send back the DIGEST_VALIDATION_RESP message.");

                VerifyMessageSyntxDigestInvalidResp((uint)result, digestValidationResponse.AuthDataSize);
            }

            return((Status)result);
        }
        /// <summary>
        /// Verify response data structure for NTLM is NetlogonValidationSamInfo2 or NetlogonValidationSamInfo4
        /// </summary>
        /// <param name="validationLevel">request validation data structure level</param>
        /// <param name="logonLevel">request logon level</param>
        private void VerifyNTLMDataStructure(
            _NETLOGON_VALIDATION_INFO_CLASS validationLevel,
            _NETLOGON_LOGON_INFO_CLASS logonLevel)
        {
            if (validationLevel == _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo)
            {
                //
                //Verify MS-APDS requirment:MS-APDS_R100136
                //
                Site.CaptureRequirementIfAreEqual <_NETLOGON_VALIDATION_INFO_CLASS>(
                    _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo,
                    validationLevel,
                    100136,
                    @"If there is a successful match[the local copy of password matches with the one sent in the 
                    request ], the domain controller MUST return data with ValidationInformation containing a reference 
                    to NETLOGON_VALIDATION_SAM_INFO ([MS-NRPC] section 2.2.1.4.11), if the ValidationLevel in the 
                    request is NetlogonValidationSamInfo.");
            }

            if (validationLevel == _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo2)
            {
                //
                //Verify MS-APDS requirment:MS-APDS_R136
                //this capture function is invoked when the return value is success,
                //It means that the local copy of password must match with the one sent in the request
                //
                Site.CaptureRequirementIfAreEqual <_NETLOGON_VALIDATION_INFO_CLASS>(
                    _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo2,
                    validationLevel,
                    136,
                    @"If the local copy of password matches with the one sent in the request, and the  ValidationLevel in 
                    the request is NetlogonValidationSamInfo2, then domain controller MUST return data with ValidationInformation 
                    containing a reference to  NETLOGON_VALIDATION_SAM_INFO2.");
            }

            if (validationLevel == _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4)
            {
                //
                //Verify MS-APDS requirment:MS-APDS_R135
                //
                Site.CaptureRequirementIfAreEqual <_NETLOGON_VALIDATION_INFO_CLASS>(
                    _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4,
                    validationLevel,
                    135,
                    @"If the local copy of password matches with the one sent in the request, and the  ValidationLevel 
                    in the request is NetlogonValidationSamInfo4, then domain controller MUST return data with 
                    ValidationInformation containing a reference to NETLOGON_VALIDATION_SAM_INFO4.");
                //
                //Verify MS-APDS requirment:MS-APDS_R122
                //
                Site.CaptureRequirementIfAreEqual <_NETLOGON_VALIDATION_INFO_CLASS>(
                    _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4,
                    validationLevel,
                    122,
                    @"The DC MUST send the NETLOGON_VALIDATION_SAM_INFO4 structures back to the NTLM server");

                if (logonLevel == _NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkInformation)
                {
                    //
                    //Configured in PTFConfig file,default SHOULD to true and MAY to false.
                    //
                    string isR120Implemented = "true";
                    //
                    //Check OS version
                    //
                    if (isWindows)
                    {
                        //
                        //Verify MS-APDS requirment:MS-APDS_R100120
                        //
                        Site.CaptureRequirementIfAreEqual <int>(
                            6,
                            (int)validationLevel,
                            100120,
                            @"In Windows, in NTLM Network logon, NETLOGON_VALIDATION_SAM_INFO4 data structures are 
                            returned by the server.");

                        if (null == isR120Implemented)
                        {
                            Site.Properties.Add("R120Implemented", Boolean.TrueString);
                            isR120Implemented = Boolean.TrueString;
                        }
                    }
                    if (null != isR120Implemented)
                    {
                        bool implSigns   = Boolean.Parse(isR120Implemented);
                        bool isSatisfied = ((int)_NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4 == 6);
                        //
                        //Verify MS-APDS requirment:MS-APDS_R120
                        //
                        Site.CaptureRequirementIfAreEqual <Boolean>(
                            implSigns,
                            isSatisfied,
                            120,
                            string.Format(@"In NTLM Network logon, NETLOGON_VALIDATION_SAM_INFO4 data structures SHOULD be returned 
                                            by the server. This requirement is {0} implemented.", implSigns? "":"not"));
                    }
                }
            }
        }
        public void NRPC_Traditional05_VerifyOutOfSequenceMessage()
        {
            PlatformType platform;
            HRESULT      result = HRESULT.ERROR_SUCCESS;

            Site.Log.Add(LogEntryKind.Comment, "Call GetPlatform");

            nrpcServerAdapter.GetPlatform(out platform);

            Site.Log.Add(LogEntryKind.Comment, "Return GetPlatform(out {0})", platform);


            Site.Log.Add(LogEntryKind.Comment, "Call ConfigServer");

            nrpcServerSutControlAdapter.ConfigServer(true, false);

            Site.Log.Add(LogEntryKind.Comment, "Return ConfigServer");

            NrpcServerAdapter adapter = new NrpcServerAdapter();

            adapter.Initialize(Site);

            using (this.nrpcClient = NrpcClient.CreateNrpcClient(adapter.PrimaryDomainDnsName))
            {
                this.nrpcClient.Context.NegotiateFlags = (NrpcNegotiateFlags)NrpcServerAdapter.NegotiateFlags;
                MachineAccountCredential machineCredential = new MachineAccountCredential(
                    adapter.PrimaryDomainDnsName,
                    adapter.ENDPOINTNetbiosName,
                    adapter.ENDPOINTPassword);
                NrpcClientSecurityContext secuContext = new NrpcClientSecurityContext(
                    adapter.PrimaryDomainDnsName,
                    adapter.PDCNetbiosName,
                    machineCredential,
                    true,
                    this.nrpcClient.Context.NegotiateFlags);
                AccountCredential accountCredential = new AccountCredential(
                    adapter.PrimaryDomainDnsName,
                    adapter.DomainAdministratorName,
                    adapter.DomainUserPassword);
                try
                {
                    this.nrpcClient.BindOverNamedPipe(
                        adapter.PDCNetbiosName,
                        accountCredential,
                        secuContext,
                        adapter.timeOut);
                }
                catch (Exception e)
                {
                    Site.Log.Add(LogEntryKind.Debug, "Failed to bind NamedPipe to " + adapter.PDCNetbiosName + "due to reason: " + e.Message);
                    Site.Assert.Fail("Failed on init NRPC client on transport NamedPipe");
                }
                this.nrpcClient.Context.SequenceNumber++;

                _NETLOGON_LOGON_INFO_CLASS logonLevelInfoClass = _NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation;
                _NETLOGON_LEVEL            logonLevel          = this.nrpcClient.CreateNetlogonLevel(
                    logonLevelInfoClass,
                    NrpcParameterControlFlags.AllowLogonWithComputerAccount,
                    adapter.PrimaryDomainDnsName,
                    adapter.DomainAdministratorName,
                    adapter.DomainUserPassword);

                // Client calls EncryptNetlogonLevel
                _NETLOGON_LEVEL?encryptedLogonLevel = this.nrpcClient.EncryptNetlogonLevel(
                    logonLevelInfoClass,
                    logonLevel);
                _NETLOGON_AUTHENTICATOR?serverAuthenticator  = this.nrpcClient.CreateEmptyNetlogonAuthenticator();
                _NETLOGON_AUTHENTICATOR?clientAuthenticator  = this.nrpcClient.ComputeNetlogonAuthenticator();
                _NETLOGON_VALIDATION?   validationInfomation = null;
                byte?authoritative = null;

                try
                {
                    result = (HRESULT)this.nrpcClient.NetrLogonSamLogon(
                        adapter.PDCNetbiosName,
                        adapter.ENDPOINTNetbiosName,
                        clientAuthenticator,
                        ref serverAuthenticator,
                        logonLevelInfoClass,
                        encryptedLogonLevel,
                        _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo2,
                        out validationInfomation,
                        out authoritative);
                }
                catch (InvalidOperationException e)
                {
                    result = (HRESULT)int.Parse(e.Message, CultureInfo.InvariantCulture);
                }

                // If the sequence number in security context is out of sequence, the server will return an error message.
                Site.CaptureRequirementIfAreNotEqual <HRESULT>(
                    HRESULT.ERROR_SUCCESS,
                    result,
                    853,
                    @"[In Receiving an Initial Netlogon Signature Token,  The following steps are 
                performed to verify the data  and to decrypt with AES if negotiated, otherwise 
                RC4 if required: in step 7: ] If these two [SequenceNumber  and CopySeqNumber ] 
                do not match, an error is returned indicating that out-of-sequence data was received.");
            }
        }
        /// <summary>
        /// Create an instance of NETLOGON_LEVEL structure 
        /// based on logonLevel parameter passed to the method.<para/>
        /// This method only supports logonLevel equals to 
        /// NetlogonInteractiveInformation or 
        /// NetlogonNetworkInformation or 
        /// NetlogonServiceInformation or 
        /// NetlogonInteractiveTransitiveInformation or
        /// NetlogonNetworkTransitiveInformation or
        /// NetlogonServiceTransitiveInformation.
        /// </summary>
        /// <param name="logonLevel">
        /// A NETLOGON_LOGON_INFO_CLASS structure, as specified in section 2.2.1.4.16, 
        /// that specifies the type of the logon information.
        /// This method only supports logonLevel equals to 
        /// NetlogonInteractiveInformation or 
        /// NetlogonNetworkInformation or 
        /// NetlogonServiceInformation or 
        /// NetlogonInteractiveTransitiveInformation or
        /// NetlogonNetworkTransitiveInformation or
        /// NetlogonServiceTransitiveInformation.
        /// </param>
        /// <param name="parameterControl">
        /// A set of bit flags that contain information pertaining 
        /// to the logon validation processing.
        /// </param>
        /// <param name="domainName">
        /// Contains the NetBIOS name of the domain of the account.
        /// </param>
        /// <param name="userName">
        /// Contains the name of the user.
        /// </param>
        /// <param name="password">
        /// The password.
        /// </param>
        /// <returns>
        /// Created but not-yet-encrypted NETLOGON_LEVEL structure.
        /// </returns>
        /// <exception cref="ArgumentException">
        /// Thrown when logonLevel is not supported by the method.
        /// </exception>
        public _NETLOGON_LEVEL CreateNetlogonLevel(
            _NETLOGON_LOGON_INFO_CLASS logonLevel,
            NrpcParameterControlFlags parameterControl,
            string domainName,
            string userName,
            string password)
        {
            _NETLOGON_LEVEL netlogonLevel = new _NETLOGON_LEVEL();
            byte[] lmOwf;
            byte[] ntOwf;
            byte[] lmChallenge;
            byte[] ntChallengeResponse;
            byte[] lmChallengeResponse;

            //Identity: A NETLOGON_LOGON_IDENTITY_INFO structure, as specified in section 2.2.1.4.15,
            //that contains information about the logon identity.
            _NETLOGON_LOGON_IDENTITY_INFO identityInfo = NrpcUtility.CreateNetlogonIdentityInfo(
                parameterControl,
                domainName,
                userName,
                context.ClientComputerName);

            switch (logonLevel)
            {
                case _NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation:
                    //LmOwfPassword: LM_OWF_PASSWORD structure, as specified in section 2.2.1.1.3,
                    //that contains the LMOWFv1 of a password.
                    //LMOWFv1 is specified in NTLM v1 Authentication in [MS-NLMP] section 3.3.1.
                    lmOwf = NlmpUtility.LmOWF(NlmpVersion.v1, domainName, userName, password);
                    //NtOwfPassword: An NT_OWF_PASSWORD structure, as specified in section 2.2.1.1.4,
                    //that contains the NTOWFv1 of a password.
                    //NTOWFv1 is specified in NTLM v1 Authentication in [MS-NLMP] section 3.3.1.
                    ntOwf = NlmpUtility.NtOWF(NlmpVersion.v1, domainName, userName, password);

                    netlogonLevel.LogonInteractive = new _NETLOGON_INTERACTIVE_INFO[1];
                    netlogonLevel.LogonInteractive[0].Identity = identityInfo;
                    netlogonLevel.LogonInteractive[0].LmOwfPassword = new _LM_OWF_PASSWORD();
                    netlogonLevel.LogonInteractive[0].LmOwfPassword.data = NrpcUtility.CreateCypherBlocks(lmOwf);
                    netlogonLevel.LogonInteractive[0].NtOwfPassword = new _NT_OWF_PASSWORD();
                    netlogonLevel.LogonInteractive[0].NtOwfPassword.data = NrpcUtility.CreateCypherBlocks(ntOwf);
                    break;

                case _NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkInformation:
                    //LmChallenge: LM_CHALLENGE structure, as specified in section 2.2.1.4.1,
                    //that contains the network authentication challenge.
                    //For details about challenges, see [MS-NLMP].
                    lmChallenge = NrpcUtility.GenerateNonce(NrpcUtility.NL_CREDENTIAL_LENGTH);
                    //NtChallengeResponse: String that contains the NT response (see [MS-NLMP])
                    //to the network authentication challenge.
                    lmOwf = NlmpUtility.GetResponseKeyLm(NlmpVersion.v1, domainName, userName, password);
                    lmChallengeResponse = NlmpUtility.DESL(lmOwf, lmChallenge);
                    //LmChallengeResponse: String that contains the LAN Manager response
                    //(see [MS-NLMP]) to the network authentication challenge.
                    ntOwf = NlmpUtility.GetResponseKeyNt(NlmpVersion.v1, domainName, userName, password);
                    ntChallengeResponse = NlmpUtility.DESL(ntOwf, lmChallenge);

                    netlogonLevel.LogonNetwork = new _NETLOGON_NETWORK_INFO[1];
                    netlogonLevel.LogonNetwork[0].Identity = identityInfo;
                    netlogonLevel.LogonNetwork[0].LmChallenge = new LM_CHALLENGE();
                    netlogonLevel.LogonNetwork[0].LmChallenge.data = lmChallenge;
                    netlogonLevel.LogonNetwork[0].LmChallengeResponse = NrpcUtility.CreateString(lmChallengeResponse);
                    netlogonLevel.LogonNetwork[0].NtChallengeResponse = NrpcUtility.CreateString(ntChallengeResponse);
                    break;

                case _NETLOGON_LOGON_INFO_CLASS.NetlogonServiceInformation:
                    //LmOwfPassword: LM_OWF_PASSWORD structure, as specified in section 2.2.1.1.3,
                    //that contains the LMOWFv1 of a password.
                    //LMOWFv1 is specified in NTLM v1 Authentication in [MS-NLMP] section 3.3.1.
                    lmOwf = NlmpUtility.LmOWF(NlmpVersion.v1, domainName, userName, password);
                    //NtOwfPassword: NT_OWF_PASSWORD structure, as specified in section 2.2.1.1.4,
                    //that contains the NTOWFv1 of a password.
                    //NTOWFv1 is specified in NTLM v1 Authentication in [MS-NLMP] section 3.3.1.
                    ntOwf = NlmpUtility.NtOWF(NlmpVersion.v1, domainName, userName, password);

                    netlogonLevel.LogonService = new _NETLOGON_SERVICE_INFO[1];
                    netlogonLevel.LogonService[0].Identity = identityInfo;
                    netlogonLevel.LogonService[0].LmOwfPassword = new _LM_OWF_PASSWORD();
                    netlogonLevel.LogonService[0].LmOwfPassword.data = NrpcUtility.CreateCypherBlocks(lmOwf);
                    netlogonLevel.LogonService[0].NtOwfPassword = new _NT_OWF_PASSWORD();
                    netlogonLevel.LogonService[0].NtOwfPassword.data = NrpcUtility.CreateCypherBlocks(ntOwf);
                    break;

                case _NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveTransitiveInformation:
                    lmOwf = NlmpUtility.LmOWF(NlmpVersion.v1, domainName, userName, password);
                    ntOwf = NlmpUtility.NtOWF(NlmpVersion.v1, domainName, userName, password);

                    netlogonLevel.LogonInteractiveTransitive = new _NETLOGON_INTERACTIVE_INFO[1];
                    netlogonLevel.LogonInteractiveTransitive[0].Identity = identityInfo;
                    netlogonLevel.LogonInteractiveTransitive[0].LmOwfPassword = new _LM_OWF_PASSWORD();
                    netlogonLevel.LogonInteractiveTransitive[0].LmOwfPassword.data
                        = NrpcUtility.CreateCypherBlocks(lmOwf);
                    netlogonLevel.LogonInteractiveTransitive[0].NtOwfPassword = new _NT_OWF_PASSWORD();
                    netlogonLevel.LogonInteractiveTransitive[0].NtOwfPassword.data
                        = NrpcUtility.CreateCypherBlocks(ntOwf);
                    break;

                case _NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation:
                    lmChallenge = NrpcUtility.GenerateNonce(NrpcUtility.NL_CREDENTIAL_LENGTH);
                    lmOwf = NlmpUtility.GetResponseKeyLm(NlmpVersion.v1, domainName, userName, password);
                    lmChallengeResponse = NlmpUtility.DESL(lmOwf, lmChallenge);
                    ntOwf = NlmpUtility.GetResponseKeyNt(NlmpVersion.v1, domainName, userName, password);
                    ntChallengeResponse = NlmpUtility.DESL(ntOwf, lmChallenge);

                    netlogonLevel.LogonNetworkTransitive = new _NETLOGON_NETWORK_INFO[1];
                    netlogonLevel.LogonNetworkTransitive[0].Identity = identityInfo;
                    netlogonLevel.LogonNetworkTransitive[0].LmChallenge = new LM_CHALLENGE();
                    netlogonLevel.LogonNetworkTransitive[0].LmChallenge.data = lmChallenge;
                    netlogonLevel.LogonNetworkTransitive[0].LmChallengeResponse
                        = NrpcUtility.CreateString(lmChallengeResponse);
                    netlogonLevel.LogonNetworkTransitive[0].NtChallengeResponse
                        = NrpcUtility.CreateString(ntChallengeResponse);
                    break;

                case _NETLOGON_LOGON_INFO_CLASS.NetlogonServiceTransitiveInformation:
                    lmOwf = NlmpUtility.LmOWF(NlmpVersion.v1, domainName, userName, password);
                    ntOwf = NlmpUtility.NtOWF(NlmpVersion.v1, domainName, userName, password);

                    netlogonLevel.LogonServiceTransitive = new _NETLOGON_SERVICE_INFO[1];
                    netlogonLevel.LogonServiceTransitive[0].Identity = identityInfo;
                    netlogonLevel.LogonServiceTransitive[0].LmOwfPassword = new _LM_OWF_PASSWORD();
                    netlogonLevel.LogonServiceTransitive[0].LmOwfPassword.data = NrpcUtility.CreateCypherBlocks(lmOwf);
                    netlogonLevel.LogonServiceTransitive[0].NtOwfPassword = new _NT_OWF_PASSWORD();
                    netlogonLevel.LogonServiceTransitive[0].NtOwfPassword.data = NrpcUtility.CreateCypherBlocks(ntOwf);
                    break;

                case _NETLOGON_LOGON_INFO_CLASS.NetlogonGenericInformation:
                default:
                    throw new ArgumentException("logonLevel is not supported by the method.", "logonLevel");
            }

            return netlogonLevel;
        }
        public _NETLOGON_LEVEL CreateNetlogonLevel(
            _NETLOGON_LOGON_INFO_CLASS logonLevel,
            string logonDomainName,
            NrpcParameterControlFlags parameterControl,
            string userName,
            string workstation,
            string packageName,
            byte[] logonData)
        {
            if (logonLevel != _NETLOGON_LOGON_INFO_CLASS.NetlogonGenericInformation)
            {
                throw new ArgumentException("logonLevel is not supported by the method.", "logonLevel");
            }

            _NETLOGON_LEVEL netlogonLevel = new _NETLOGON_LEVEL();

            netlogonLevel.LogonGeneric = new _NETLOGON_GENERIC_INFO[1];
            netlogonLevel.LogonGeneric[0].Identity = new _NETLOGON_LOGON_IDENTITY_INFO();
            netlogonLevel.LogonGeneric[0].Identity.LogonDomainName = DtypUtility.ToRpcUnicodeString(logonDomainName);
            netlogonLevel.LogonGeneric[0].Identity.ParameterControl = (uint)parameterControl;
            netlogonLevel.LogonGeneric[0].Identity.UserName = DtypUtility.ToRpcUnicodeString(userName);
            netlogonLevel.LogonGeneric[0].Identity.Workstation = DtypUtility.ToRpcUnicodeString(workstation);
            netlogonLevel.LogonGeneric[0].Identity.Reserved = DtypUtility.ToOldLargeInteger(0);
            netlogonLevel.LogonGeneric[0].PackageName = DtypUtility.ToRpcUnicodeString(packageName);
            netlogonLevel.LogonGeneric[0].DataLength = (uint)logonData.Length;
            netlogonLevel.LogonGeneric[0].LogonData = logonData;

            return netlogonLevel;
        }
        /// <summary>
        ///  The NetrLogonSamLogonWithFlags method Supported in windows_xpwindows_server_2003,
        ///  windows_vista, windows_server_2008, windows_7, and
        ///  windows_server_7. handles logon requests for the SAM
        ///  accounts. Opnum: 45 
        /// </summary>
        /// <param name="logonServer">
        ///  The custom RPC binding handle.
        /// </param>
        /// <param name="computerName">
        ///  The Unicode string that contains the NetBIOS name of
        ///  the client computer calling this method.
        /// </param>
        /// <param name="authenticator">
        ///  A pointer to a NETLOGON_AUTHENTICATOR structure, 
        ///  that contains the client authenticator.
        /// </param>
        /// <param name="returnAuthenticator">
        ///  A pointer to a NETLOGON_AUTHENTICATOR structure, 
        ///  that contains the server return
        ///  authenticator.
        /// </param>
        /// <param name="logonLevel">
        ///  A NETLOGON_LOGON_INFO_CLASS structure, 
        ///  that specifies the type of logon information
        ///  passed in the LogonInformation parameter.
        /// </param>
        /// <param name="logonInformation">
        ///  A pointer to a NETLOGON_LEVEL structure, 
        ///  that describes the logon request information.
        /// </param>
        /// <param name="validationLevel">
        ///  A NETLOGON_VALIDATION_INFO_CLASS enumerated type, 
        ///  that contains the validation
        ///  level requested by the client.
        /// </param>
        /// <param name="validationInformation">
        ///  A pointer to a NETLOGON_VALIDATION structure, 
        ///  that describes the user validation information
        ///  returned to the client. The type of the NETLOGON_VALIDATION
        ///  used is determined by the value of the ValidationLevel
        ///  parameter.
        /// </param>
        /// <param name="authoritative">
        ///  A pointer to a char value representing a Boolean condition.
        ///  FALSE is indicated by the value 0x00; TRUE SHOULD be
        ///  indicated by the value 0x01 and MAY also be indicated
        ///  by any nonzero value. Windows uses the value of 0x01
        ///  as the representation of TRUE and 0x00 for FALSE. This
        ///  Boolean value indicates whether the validation information
        ///  is final. This field is necessary because the request
        ///  might be forwarded through multiple servers. A value
        ///  of TRUE indicates that the validation information is
        ///  final and MUST remain unchanged.
        /// </param>
        /// <param name="extraFlags">
        ///  A pointer to a set of bit flags that specify delivery
        ///  settings. A flag is TRUE (or set) if its value is equal
        ///  to 1. The value is constructed from zero or more bit
        ///  flags from the following table.
        /// </param>
        /// <returns>
        /// The method returns 0x00000000 on success; 
        /// otherwise, it returns a nonzero error code.
        /// </returns>
        public NtStatus NetrLogonSamLogonWithFlags(
            string logonServer,
            string computerName,
            _NETLOGON_AUTHENTICATOR? authenticator,
            ref _NETLOGON_AUTHENTICATOR? returnAuthenticator,
            _NETLOGON_LOGON_INFO_CLASS logonLevel,
            _NETLOGON_LEVEL? logonInformation,
            _NETLOGON_VALIDATION_INFO_CLASS validationLevel,
            out _NETLOGON_VALIDATION? validationInformation,
            out byte? authoritative,
            ref NrpcNetrLogonSamLogonExtraFlags? extraFlags)
        {
            uint? flags = (uint?)extraFlags;

            NtStatus status = rpc.NetrLogonSamLogonWithFlags(
                logonServer,
                computerName,
                authenticator,
                ref returnAuthenticator,
                logonLevel,
                logonInformation,
                validationLevel,
                out validationInformation,
                out authoritative,
                ref flags);

            context.ConnectionStatus = status;
            extraFlags = (NrpcNetrLogonSamLogonExtraFlags?)flags;
            return status;
        }
        /// <summary>
        ///  The NetrLogonSamLogonEx method Supported in windows_2000_server,
        ///  windows_xp, windows_server_2003, windows_vista, windows_server_2008,
        ///  windows_7, and windows_server_7. provides an extension
        ///  to NetrLogonSamLogon that accepts an extra flags parameter
        ///  and uses Secure RPC ([MS-RPCE]) instead of
        ///  Netlogon authenticators. This method handles logon
        ///  requests for the SAM accounts and allows for generic
        ///  pass-through authentication.
        ///  For more information about fields and structures
        ///  used by Netlogon pass-through methods.
        ///  Opnum: 39 
        /// </summary>
        /// <param name="contextHandle">
        ///  A primitive RPC handle that identifies a particular
        ///  client/server binding.
        /// </param>
        /// <param name="logonServer">
        ///  The null-terminated Unicode string that contains the
        ///  NetBIOS name of the server that will handle the logon
        ///  request.
        /// </param>
        /// <param name="computerName">
        ///  The null-terminated Unicode string that contains the
        ///  NetBIOS name of the client computer sending the logon
        ///  request.
        /// </param>
        /// <param name="logonLevel">
        ///  A NETLOGON_LOGON_INFO_CLASS structure, 
        ///  that specifies the type of the logon information
        ///  passed in the LogonInformation parameter.
        /// </param>
        /// <param name="logonInformation">
        ///  A pointer to a NETLOGON_LEVEL structure, 
        ///  that describes the logon request information.
        /// </param>
        /// <param name="validationLevel">
        ///  A NETLOGON_VALIDATION_INFO_CLASS enumerated type, 
        ///  that contains the validation
        ///  level requested by the client.
        /// </param>
        /// <param name="validationInformation">
        ///  A pointer to a NETLOGON_VALIDATION structure, 
        ///  that describes the user validation information
        ///  returned to the client. The type of the NETLOGON_VALIDATION
        ///  used is determined by the value of the ValidationLevel
        ///  parameter.
        /// </param>
        /// <param name="authoritative">
        ///  A pointer to a char value that represents a Boolean
        ///  condition. FALSE is indicated by the value 0x00, and
        ///  TRUE SHOULDwindows uses the value 0x01 as the representation
        ///  of TRUE and 0x00 for FALSE. be indicated by the value
        ///  0x01 and MAY also be indicated by any nonzero value.
        ///  This Boolean value indicates whether the validation
        ///  information is final. This field is necessary because
        ///  the request might be forwarded through multiple servers.
        ///  The value TRUE indicates that the validation information
        ///  is final and MUST remain unchanged. The Authoritative
        ///  parameter indicates whether the response to this call
        ///  is final or if the same request can be sent to another
        ///  server. The value SHOULD be set to FALSE if the server
        ///  encounters a transient error, and the client can resend
        ///  the request to another server. If the same request
        ///  is known to fail in all subsequent requests, the server
        ///  SHOULD return TRUE.
        /// </param>
        /// <param name="extraFlags">
        ///  A pointer to a set of bit flags that specify delivery
        ///  settings. A flag is TRUE (or set) if its value is equal
        ///  to 1. Output flags MUST be the same as input. The value
        ///  is constructed from zero or more bit flags from the
        ///  following table.
        /// </param>
        /// <returns>
        /// The method returns 0x00000000 on success; 
        /// otherwise, it returns a nonzero error code.
        /// </returns>
        public NtStatus NetrLogonSamLogonEx(
            IntPtr contextHandle,
            string logonServer,
            string computerName,
            _NETLOGON_LOGON_INFO_CLASS logonLevel,
            _NETLOGON_LEVEL? logonInformation,
            _NETLOGON_VALIDATION_INFO_CLASS validationLevel,
            out _NETLOGON_VALIDATION? validationInformation,
            out byte? authoritative,
            ref NrpcNetrLogonSamLogonExtraFlags? extraFlags)
        {
            uint? flags = (uint?)extraFlags;

            NtStatus status = rpc.NetrLogonSamLogonEx(
                contextHandle,
                logonServer,
                computerName,
                logonLevel,
                logonInformation,
                validationLevel,
                out validationInformation,
                out authoritative,
                ref flags);

            context.ConnectionStatus = status;
            extraFlags = (NrpcNetrLogonSamLogonExtraFlags?)flags;
            return status;
        }
        /// <summary>
        ///  The NetrLogonSamLogon method This method was used in
        ///  windows_nt_4_0. It was superseded by the NetrLogonSamLogonWithFlags
        ///  method in windows_2000_server, windows_xp,
        ///  windows_server_2003, windows_vista, and windows_server_2008,
        ///  windows_7, and windows_server_7. is a predecessor to
        ///  the NetrLogonSamLogonWithFlags method. All
        ///  parameters of this method have the same meanings as
        ///  the identically named parameters of the NetrLogonSamLogonWithFlags
        ///  method. Opnum: 2 
        /// </summary>
        /// <param name="logonServer">
        ///  LogonServer parameter.
        /// </param>
        /// <param name="computerName">
        ///  ComputerName parameter.
        /// </param>
        /// <param name="authenticator">
        ///  Authenticator parameter.
        /// </param>
        /// <param name="returnAuthenticator">
        ///  ReturnAuthenticator parameter.
        /// </param>
        /// <param name="logonLevel">
        ///  LogonLevel parameter.
        /// </param>
        /// <param name="logonInformation">
        ///  LogonInformation parameter.
        /// </param>
        /// <param name="validationLevel">
        ///  ValidationLevel parameter.
        /// </param>
        /// <param name="validationInformation">
        ///  ValidationInformation parameter.
        /// </param>
        /// <param name="authoritative">
        ///  Authoritative parameter.
        /// </param>
        /// <returns>
        /// The method returns 0x00000000 on success; 
        /// otherwise, it returns a nonzero error code.
        /// </returns>
        public NtStatus NetrLogonSamLogon(
            string logonServer,
            string computerName,
            _NETLOGON_AUTHENTICATOR? authenticator,
            ref _NETLOGON_AUTHENTICATOR? returnAuthenticator,
            _NETLOGON_LOGON_INFO_CLASS logonLevel,
            _NETLOGON_LEVEL? logonInformation,
            _NETLOGON_VALIDATION_INFO_CLASS validationLevel,
            out _NETLOGON_VALIDATION? validationInformation,
            out byte? authoritative)
        {
            NtStatus status = rpc.NetrLogonSamLogon(
                logonServer,
                computerName,
                authenticator,
                ref returnAuthenticator,
                logonLevel,
                logonInformation,
                validationLevel,
                out validationInformation,
                out authoritative);

            //ConnectionStatus: A 4-byte value that contains the most recent
            //connection status return value (section 3.4.5.3.1) last returned
            //during secure channel establishment or by a method requiring
            //session key establishment (section 3.1.4.6).
            context.ConnectionStatus = status;
            return status;
        }
        /// <summary>
        ///  The NetrLogonSamLogoff method handles logoff requests
        ///  for the SAM accounts. Opnum: 3 
        /// </summary>
        /// <param name="logonServer">
        ///  The custom RPC binding handle.
        /// </param>
        /// <param name="computerName">
        ///  The Unicode string that contains the NetBIOS name of
        ///  the client computer calling this method.
        /// </param>
        /// <param name="authenticator">
        ///  A pointer to a NETLOGON_AUTHENTICATOR structure, 
        ///  that contains the client authenticator.
        /// </param>
        /// <param name="returnAuthenticator">
        ///  A pointer to a NETLOGON_AUTHENTICATOR structure, 
        ///  that contains the server return
        ///  authenticator.
        /// </param>
        /// <param name="logonLevel">
        ///  A NETLOGON_LOGON_INFO_CLASS structure, 
        ///  that identifies the type of logon information
        ///  in the LogonInformation union.
        /// </param>
        /// <param name="logonInformation">
        ///  A pointer to a NETLOGON_LEVEL structure, 
        ///  that describes the logon information.
        /// </param>
        /// <returns>
        /// The method returns 0x00000000 on success; 
        /// otherwise, it returns a nonzero error code.
        /// </returns>
        public NtStatus NetrLogonSamLogoff(
            string logonServer,
            string computerName,
            _NETLOGON_AUTHENTICATOR? authenticator,
            ref _NETLOGON_AUTHENTICATOR? returnAuthenticator,
            _NETLOGON_LOGON_INFO_CLASS logonLevel,
            _NETLOGON_LEVEL? logonInformation)
        {
            NtStatus status = rpc.NetrLogonSamLogoff(
                logonServer,
                computerName,
                authenticator,
                ref returnAuthenticator,
                logonLevel,
                logonInformation);

            context.ConnectionStatus = status;
            return status;
        }
        /// <summary>
        /// Encrypt a NETLOGON_LEVEL structure based on 
        /// logonLevel parameter passed to the method. 
        /// This method support RC4 encryption only.
        /// </summary>
        /// <param name="logonLevel">
        /// A NETLOGON_LOGON_INFO_CLASS structure, as specified in section 2.2.1.4.16, 
        /// that specifies the type of the logon information.
        /// </param>
        /// <param name="logonInformation">
        /// A NETLOGON_LEVEL structure to be encrypted.
        /// </param>
        /// <returns>The encrypted NETLOGON_LEVEL structure.</returns>
        /// <exception cref="ArgumentException">
        /// Thrown when logonLevel or logonInformation is invalid.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Thrown when session key is not negotiated.
        /// </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 _NETLOGON_LEVEL EncryptNetlogonLevel(
            _NETLOGON_LOGON_INFO_CLASS logonLevel,
            _NETLOGON_LEVEL logonInformation)
        {
            ValidateSecureChannelExists();

            switch (logonLevel)
            {
                case _NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation:
                    //If the LogonLevel is NetlogonInteractiveInformation or
                    //NetlogonInteractiveTransitiveInformation, then encrypt<102>
                    //the LmOwfPassword and NtOwfPassword members in the
                    //NETLOGON_INTERACTIVE_INFO structure.
                    if (logonInformation.LogonInteractive == null
                        || logonInformation.LogonInteractive.Length != 1)
                    {
                        throw new ArgumentException("logonInformation is invalid.", "logonInformation");
                    }

                    EncryptLmAndNtOwfPassword(
                        ref logonInformation.LogonInteractive[0].LmOwfPassword,
                        ref logonInformation.LogonInteractive[0].NtOwfPassword);
                    break;

                case _NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveTransitiveInformation:
                    if (logonInformation.LogonInteractiveTransitive == null
                        || logonInformation.LogonInteractiveTransitive.Length != 1)
                    {
                        throw new ArgumentException("logonInformation is invalid.", "logonInformation");
                    }

                    EncryptLmAndNtOwfPassword(
                        ref logonInformation.LogonInteractiveTransitive[0].LmOwfPassword,
                        ref logonInformation.LogonInteractiveTransitive[0].NtOwfPassword);
                    break;

                case _NETLOGON_LOGON_INFO_CLASS.NetlogonServiceInformation:
                    //If the LogonLevel is NetlogonServiceInformation or
                    //NetlogonServiceTransitiveInformation, then encrypt<103>
                    //the LmOwfPassword and NtOwfPassword members in the
                    //NETLOGON_SERVICE_INFO structure.
                    if (logonInformation.LogonService == null
                        || logonInformation.LogonService.Length != 1)
                    {
                        throw new ArgumentException("logonInformation is invalid.", "logonInformation");
                    }

                    EncryptLmAndNtOwfPassword(
                        ref logonInformation.LogonService[0].LmOwfPassword,
                        ref logonInformation.LogonService[0].NtOwfPassword);
                    break;

                case _NETLOGON_LOGON_INFO_CLASS.NetlogonServiceTransitiveInformation:
                    if (logonInformation.LogonServiceTransitive == null
                        || logonInformation.LogonServiceTransitive.Length != 1)
                    {
                        throw new ArgumentException("logonInformation is invalid.", "logonInformation");
                    }

                    EncryptLmAndNtOwfPassword(
                        ref logonInformation.LogonServiceTransitive[0].LmOwfPassword,
                        ref logonInformation.LogonServiceTransitive[0].NtOwfPassword);
                    break;

                case _NETLOGON_LOGON_INFO_CLASS.NetlogonGenericInformation:
                    //If the LogonLevel is NetlogonGenericInformation,
                    //then encrypt<104> the LogonData member in the
                    //NETLOGON_GENERIC_INFO structure.
                    if (logonInformation.LogonGeneric == null
                        || logonInformation.LogonGeneric.Length != 1)
                    {
                        throw new ArgumentException("logonInformation is invalid.", "logonInformation");
                    }

                    //Encrypt the ClearNewPassword parameter using the RC4 algorithm
                    //and the session key established as the encryption key.
                    logonInformation.LogonGeneric[0].LogonData = NrpcUtility.EncryptBuffer(
                        IsAesOrRc4Negotiated(),
                        context.SessionKey,
                        logonInformation.LogonGeneric[0].LogonData);
                    break;

                case _NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkInformation:
                case _NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation:
                    //If the LogonLevel is NetlogonNetworkInformation or
                    //NetlogonNetworkTransitiveInformation, then encrypt the
                    //UserSessionKey and the first two elements of the
                    //ExpansionRoom array in the NETLOGON_VALIDATION_SAM_INFO
                    //(section 2.2.1.4.11) or in the NETLOGON_VALIDATION_SAM_INFO2
                    //(section 2.2.1.4.12) structure.

                    //TODO: TDI 48320, there're no UserSessionKey and ExpansionRoom in NETLOGON_INFO class.

                    break;

                default:
                    throw new ArgumentException("logonLevel is invalid.", "logonLevel");
            }

            return logonInformation;
        }