Example #1
0
        /// <summary>
        /// This takes the given SecBuffers, which are used by SSPI method DecryptMessage.
        /// </summary>
        /// <param name="securityBuffers">SecBuffer.Encrypted data will be filled in SecBuffers.</param>
        /// <returns>If successful, returns true, otherwise false.</returns>
        /// <exception cref="ArgumentNullException">Thrown when securityBuffers is null. </exception>
        /// <exception cref="ArgumentException">Thrown when length of securityBuffers is zero or
        /// securityBuffers have null element.</exception>
        public override bool Decrypt(params SecurityBuffer[] securityBuffers)
        {
            if (securityBuffers == null)
            {
                throw new ArgumentNullException("securityBuffers");
            }

            if (securityBuffers.Length == 0)
            {
                throw new ArgumentException("Length of securityBuffer cannot be zero.", "securityBuffers");
            }

            for (int i = 0; i < securityBuffers.Length; i++)
            {
                if (securityBuffers[i] == null)
                {
                    throw new ArgumentException("securityBuffers have null element", "securityBuffers");
                }
            }

            return(NrpcUtility.ValidateNetlogonSignatureToken(
                       ((clientSessionInfo.NegotiateFlags & NrpcNegotiateFlags.SupportsAESAndSHA2) != 0),
                       ref sequenceNumber,
                       SessionKey,
                       true,
                       true,
                       securityBuffers));
        }
Example #2
0
        /// <summary>
        /// Calculates session key based on negotiation flags
        /// </summary>
        private void ComputeSessionKey()
        {
            if (SharedSecret == null)
            {
                throw new InvalidOperationException("Not able to calculate session key, SharedSecret is null");
            }

            if (ClientChallenge == null)
            {
                throw new InvalidOperationException("Not able to calculate session key, ClientChallenge is null");
            }

            if (ServerChallenge == null)
            {
                throw new InvalidOperationException("Not able to calculate session key, ServerChallenge is null");
            }

            if ((NegotiateFlags & NrpcNegotiateFlags.SupportsAESAndSHA2) != 0)
            {
                SessionKey = NrpcUtility.ComputeSessionKey(NrpcComputeSessionKeyAlgorithm.HMACSHA256,
                                                           SharedSecret, ClientChallenge, ServerChallenge);
            }
            else if ((NegotiateFlags & NrpcNegotiateFlags.SupportsStrongKeys) != 0)
            {
                SessionKey = NrpcUtility.ComputeSessionKey(NrpcComputeSessionKeyAlgorithm.MD5,
                                                           SharedSecret, ClientChallenge, ServerChallenge);
            }
            else
            {
                SessionKey = NrpcUtility.ComputeSessionKey(NrpcComputeSessionKeyAlgorithm.DES,
                                                           SharedSecret, ClientChallenge, ServerChallenge);
            }
        }
Example #3
0
        /// <summary>
        ///  Construct Kerberos PAC pass-through logon information
        /// </summary>
        /// <param name="parameterControl">
        /// A set of bit flags that contain information pertaining to the logon validation processing.
        /// </param>
        /// <param name="domainName">domain name</param>
        /// <param name="userName">user name</param>
        /// <param name="serverName">NetBIOS name of server </param>
        /// <param name="kerbVerifyPacRequest">KERB_VERIFY_PAC_REQUEST packet</param>
        /// <returns>Kerberos PAC netlogon information structure </returns>
        public static _NETLOGON_LEVEL CreatePacLogonInfo(
            NrpcParameterControlFlags parameterControl,
            string domainName,
            string userName,
            string serverName,
            KERB_VERIFY_PAC_REQUEST kerbVerifyPacRequest)
        {
            _NETLOGON_LEVEL netLogonLevel = new _NETLOGON_LEVEL();

            byte[] logonData = TypeMarshal.ToBytes <KERB_VERIFY_PAC_REQUEST>(kerbVerifyPacRequest);

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

            netLogonLevel.LogonGeneric                = new _NETLOGON_GENERIC_INFO[1];
            netLogonLevel.LogonGeneric[0].Identity    = identityInfo;
            netLogonLevel.LogonGeneric[0].PackageName = DtypUtility.ToRpcUnicodeString(KERBEROS_PACKAGENAME);
            netLogonLevel.LogonGeneric[0].LogonData   = logonData;
            netLogonLevel.LogonGeneric[0].DataLength  = (uint)logonData.Length;

            return(netLogonLevel);
        }
Example #4
0
        /// <summary>
        /// Validates the client authenticator
        /// </summary>
        /// <param name="clientAuthenticator">the client authenticator</param>
        private void ValidateNetlogonAuthenticator(_NETLOGON_AUTHENTICATOR?clientAuthenticator)
        {
            if (SessionKey == null || StoredCredential == null)
            {
                throw new InvalidOperationException("Unable to validate client authenticator");
            }

            if (!clientAuthenticator.HasValue)
            {
                return;
            }

            NrpcComputeNetlogonCredentialAlgorithm algorithm;

            if ((NegotiateFlags & NrpcNegotiateFlags.SupportsAESAndSHA2) != 0)
            {
                algorithm = NrpcComputeNetlogonCredentialAlgorithm.AES128;
            }
            else
            {
                algorithm = NrpcComputeNetlogonCredentialAlgorithm.DESECB;
            }

            byte[] serverStoredCredential = StoredCredential;
            if (!NrpcUtility.ValidateClientNetlogonAuthenticator(
                    clientAuthenticator.Value, algorithm, ref serverStoredCredential, SessionKey))
            {
                throw new InvalidOperationException("Client authenticator isn't correct");
            }
            StoredCredential = serverStoredCredential;
        }
Example #5
0
        /// <summary>
        /// Call to this method establishes a secure channel between protocol client and
        /// protocol server and generates a session key, ehich is used for encryption of
        /// request packets and decryption of response packets.
        /// </summary>
        private void EstablishSecureChannel()
        {
            nrpcClient = NrpcClient.CreateNrpcClient(sutDomainName);
            ushort[] endPointList = NrpcUtility.QueryNrpcTcpEndpoint(serverName);

            ushort endPoint = endPointList[0];

            MachineAccountCredential machineCredential = new MachineAccountCredential(
                sutDomainName,
                clientComputerName,
                clientComputerPassword);

            nrpcClient.Context.NegotiateFlags = NrpcNegotiateFlags.SupportsAESAndSHA2
                                                | NrpcNegotiateFlags.SupportsConcurrentRpcCalls
                                                | NrpcNegotiateFlags.SupportsCrossForestTrusts
                                                | NrpcNegotiateFlags.SupportsGenericPassThroughAuthentication
                                                | NrpcNegotiateFlags.SupportsNetrLogonGetDomainInfo
                                                | NrpcNegotiateFlags.SupportsNetrLogonSendToSam
                                                | NrpcNegotiateFlags.SupportsNetrServerPasswordSet2
                                                | NrpcNegotiateFlags.SupportsRC4
                                                | NrpcNegotiateFlags.SupportsRefusePasswordChange
                                                | NrpcNegotiateFlags.SupportsRodcPassThroughToDifferentDomains
                                                | NrpcNegotiateFlags.SupportsSecureRpc
                                                | NrpcNegotiateFlags.SupportsStrongKeys
                                                | NrpcNegotiateFlags.SupportsTransitiveTrusts;

            NrpcClientSecurityContext securityContext = new NrpcClientSecurityContext(
                sutDomainName,
                sutComputerName,
                machineCredential,
                true,
                nrpcClient.Context.NegotiateFlags);

            nrpcClient.BindOverTcp(serverName, endPoint, securityContext, timeout);
        }
Example #6
0
        /// <summary>
        /// Create DPSP logon information structure
        /// </summary>
        /// <param name="parameterControl">
        /// A set of bit flags that contain information pertaining to the logon validation processing.
        /// </param>
        /// <param name="digestValidationReq">DIGEST_VALIDATION_REQ structure</param>
        /// <returns>Dpsp netlogon information structure</returns>
        public static _NETLOGON_LEVEL CreateDpspLogonInfo(
            NrpcParameterControlFlags parameterControl,
            DIGEST_VALIDATION_REQ digestValidationReq)
        {
            if (digestValidationReq.Payload == null)
            {
                throw new ArgumentException(
                          "invalid digestValidationReq parameter: the payload field is null",
                          "digestValidationReq");
            }

            _NETLOGON_LEVEL netLogonLevel = new _NETLOGON_LEVEL();

            DIGEST_VALIDATION_REQ_Payload payload =
                DIGEST_VALIDATION_REQ_Payload.Parse(digestValidationReq.Payload);

            byte[] logonData = TypeMarshal.ToBytes <DIGEST_VALIDATION_REQ>(digestValidationReq);

            //Identity: A NETLOGON_LOGON_IDENTITY_INFO structure, as specified in section MS-NRPC 2.2.1.4.15,
            //that contains information about the logon identity.
            _NETLOGON_LOGON_IDENTITY_INFO identityInfo = NrpcUtility.CreateNetlogonIdentityInfo(
                parameterControl,
                payload.Domain,
                payload.Username,
                payload.ServerName);

            netLogonLevel.LogonGeneric                = new _NETLOGON_GENERIC_INFO[1];
            netLogonLevel.LogonGeneric[0].Identity    = identityInfo;
            netLogonLevel.LogonGeneric[0].PackageName = DtypUtility.ToRpcUnicodeString(DIGEST_PACKAGENAME);
            netLogonLevel.LogonGeneric[0].LogonData   = logonData;
            netLogonLevel.LogonGeneric[0].DataLength  = (uint)logonData.Length;

            return(netLogonLevel);
        }
        /// <summary>
        /// Initialize method is not used for NRPC SSPI.<para/>
        /// NRPC SSPI will negotiate security context in its own RPC call.
        /// </summary>
        /// <param name="inToken">
        /// A token returned from server SSPI;
        /// if it's set to null, indicates to initialize a new client token.
        /// </param>
        /// <exception cref="SspiException">
        /// Thrown when server returned token is invalid.
        /// </exception>
        public override void Initialize(byte[] inToken)
        {
            if (inToken == null)
            {
                //Initialize a new token.
                if (nrpc.Context.SessionKey == null)
                {
                    //Negotiate a session key.
                    NrpcNegotiateFlags clientCapabilities = nrpc.Context.NegotiateFlags;

                    ushort[] nrpcTcpEndpoints = NrpcUtility.QueryNrpcTcpEndpoint(nrpc.Context.PrimaryName);
                    if (nrpcTcpEndpoints == null || nrpcTcpEndpoints.Length == 0)
                    {
                        throw new InvalidOperationException("Server doesn't support NRPC protocol.");
                    }

                    nrpc.BindOverTcp(
                        nrpc.Context.PrimaryName,
                        nrpcTcpEndpoints[0],
                        null,
                        timeout);
                    nrpc.NetrServerReqChallenge(credential.MachineName);
                    nrpc.NetrServerAuthenticate3(
                        credential.AccountName,
                        this.secureChannelType,
                        ref clientCapabilities,
                        credential.Password);
                }

                NL_AUTH_MESSAGE nlAuthMessage = nrpc.CreateNlAuthMessage();
                this.token = ArrayUtility.ConcatenateArrays(
                    BitConverter.GetBytes((uint)nlAuthMessage.MessageType),
                    BitConverter.GetBytes((uint)nlAuthMessage.Flags),
                    nlAuthMessage.Buffer);
                this.needContinueProcessing = true;
            }
            else
            {
                this.token = null;
                this.needContinueProcessing = false;

                NL_AUTH_MESSAGE nlAuthMessage = new NL_AUTH_MESSAGE();
                int             offset        = 0;
                nlAuthMessage.MessageType = (MessageType_Values)BitConverter.ToInt32(inToken, offset);
                offset += sizeof(int); // cannot call: Marshal.SizeOf(nlAuthMessage.MessageType);
                nlAuthMessage.Flags = (NL_AUTH_MESSAGE_Flags_Value)BitConverter.ToUInt32(inToken, offset);
                offset += sizeof(NL_AUTH_MESSAGE_Flags_Value);
                nlAuthMessage.Buffer = ArrayUtility.SubArray(inToken, offset, inToken.Length - offset);
                if (!nrpc.ValidateNlAuthMessage(nlAuthMessage))
                {
                    //validate server returned token failed.
                    throw new SspiException("Server returned token is invalid.");
                }
            }
        }
Example #8
0
        /// <summary>
        /// Validates the client credential.
        /// </summary>
        /// <param name="sessionKey">the session key negotiated</param>
        /// <param name="negotiateFlags">the negotiation flags</param>
        ///  <param name="clientChallenge">client challenge received</param>
        /// <param name="clientCredentialReceived">the client credential received</param>
        private void ValidateClientCredential(byte[] sessionKey, uint negotiateFlags, byte[] clientChallenge,
                                              _NETLOGON_CREDENTIAL?clientCredentialReceived)
        {
            if (clientCredentialReceived == null || clientCredentialReceived.Value.data == null)
            {
                throw new InvalidOperationException("Client Credential doesn't match");
            }

            byte[] clientCredentialComputed = NrpcUtility.ComputeNetlogonCredential(sessionKey, negotiateFlags,
                                                                                    clientChallenge);

            bool compareResult = ArrayUtility.CompareArrays <byte>(clientCredentialReceived.Value.data,
                                                                   clientCredentialComputed);

            if (!compareResult)
            {
                throw new InvalidOperationException("Client Credential doesn't match");
            }
            StoredCredential = clientCredentialComputed;
        }
Example #9
0
        /// <summary>
        /// Construct Nlmp pass-through interactive logon information structure
        /// from client NTLM authenticate response message
        /// </summary>
        /// <param name="parameterControl">A set of bit flags
        /// that contain information pertaining to the logon validation processing.
        /// </param>
        /// <param name="domainName">domain name</param>
        /// <param name="userName">user name</param>
        /// <param name="password">password</param>
        /// <param name="serverName">NetBIOS name of server </param>
        /// <returns>nlmp interactive logon information structure</returns>
        public static _NETLOGON_LEVEL CreateNlmpInteractiveLogonInfo(
            NrpcParameterControlFlags parameterControl,
            string domainName,
            string userName,
            string password,
            string serverName
            )
        {
            _NETLOGON_LEVEL netLogonLevel = new _NETLOGON_LEVEL();

            //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.
            byte[] 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.
            byte[] ntOwf = NlmpUtility.NtOWF(NlmpVersion.v1, domainName, userName, password);

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

            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);

            return(netLogonLevel);
        }
Example #10
0
        /// <summary>
        ///  Receives and processes remote requests to establish secure channels
        /// </summary>
        /// <param name="threadParameter">A dictionary whose key is the machine name and the
        /// value is the machine password</param>
        internal static void EstablishSecureChannel(object threadParameter)
        {
            Dictionary <string, string> machineNameToPasswordDictionary =
                threadParameter as Dictionary <string, string>;

            if (serverForSecureChannel == null)
            {
                serverForSecureChannel = new NrpcServer(null);
                serverForSecureChannel.StartTcp(tcpPort);
                //todo: support ipv6
                serverForSecureChannel.StartNamedPipe(NrpcUtility.NETLOGON_RPC_OVER_NP_WELLKNOWN_ENDPOINT, null, IPAddress.Any);
            }

            TimeSpan defaultTimeSpan = new TimeSpan(0, 0, 0, 0, DefaultTimeout);
            NrpcServerSessionContext sessionContext;

            while (!isStopped)
            {
                NrpcRequestStub request = serverForSecureChannel.ExpectRpcCall <NrpcRequestStub>(defaultTimeSpan, out sessionContext);
                switch (request.Opnum)
                {
                case NrpcMethodOpnums.NetrServerReqChallenge:
                    NrpcNetrServerReqChallengeRequest nrpcNetrServerReqChallengeRequest =
                        request as NrpcNetrServerReqChallengeRequest;
                    NrpcNetrServerReqChallengeResponse nrpcNetrServerReqChallengeResponse;

                    if (!machineNameToPasswordDictionary.ContainsKey(sessionContext.ClientComputerName))
                    {
                        nrpcNetrServerReqChallengeResponse =
                            serverForSecureChannel.CreateNetrServerReqChallengeResponse(sessionContext,
                                                                                        NrpcUtility.GenerateNonce(8), "");
                        nrpcNetrServerReqChallengeResponse.Status = NtStatus.STATUS_ACCESS_DENIED;
                    }
                    else
                    {
                        nrpcNetrServerReqChallengeResponse =
                            serverForSecureChannel.CreateNetrServerReqChallengeResponse(sessionContext,
                                                                                        NrpcUtility.GenerateNonce(8),
                                                                                        machineNameToPasswordDictionary[sessionContext.ClientComputerName]);
                    }
                    serverForSecureChannel.SendRpcCallResponse(
                        sessionContext, nrpcNetrServerReqChallengeResponse);
                    break;

                case NrpcMethodOpnums.NetrServerAuthenticate:
                    NrpcNetrServerAuthenticateRequest nrpcNetrServerAuthenticateRequest =
                        request as NrpcNetrServerAuthenticateRequest;
                    NrpcNetrServerAuthenticateResponse nrpcNetrServerAuthenticateResponse =
                        serverForSecureChannel.CreateNetrServerAuthenticateResponse(sessionContext);

                    serverForSecureChannel.SendRpcCallResponse(
                        sessionContext, nrpcNetrServerAuthenticateResponse);
                    break;

                case NrpcMethodOpnums.NetrServerAuthenticate2:
                    NrpcNetrServerAuthenticate2Request nrpcNetrServerAuthenticate2Request =
                        request as NrpcNetrServerAuthenticate2Request;
                    NrpcNetrServerAuthenticate2Response nrpcNetrServerAuthenticate2Response =
                        serverForSecureChannel.CreateNetrServerAuthenticate2Response(sessionContext,
                                                                                     (uint)sessionContext.NegotiateFlags);

                    serverForSecureChannel.SendRpcCallResponse(
                        sessionContext, nrpcNetrServerAuthenticate2Response);
                    break;

                case NrpcMethodOpnums.NetrServerAuthenticate3:
                    NrpcNetrServerAuthenticate3Request nrpcNetrServerAuthenticate3Request =
                        request as NrpcNetrServerAuthenticate3Request;
                    NrpcNetrServerAuthenticate3Response nrpcNetrServerAuthenticate3Response =
                        serverForSecureChannel.CreateNetrServerAuthenticate3Response(sessionContext,
                                                                                     (uint)sessionContext.NegotiateFlags, 100);

                    serverForSecureChannel.SendRpcCallResponse(
                        sessionContext, nrpcNetrServerAuthenticate3Response);
                    break;

                default:
                    //bypass other requests
                    break;
                }
            }

            serverForSecureChannel.StopTcp(tcpPort);
            serverForSecureChannel.StopNamedPipe(NrpcUtility.NETLOGON_RPC_OVER_NP_WELLKNOWN_ENDPOINT);
            serverForSecureChannel.Dispose();
            serverForSecureChannel = null;
        }
Example #11
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);
        }
Example #12
0
        /// <summary>
        /// Construct Nlmp pass-through network logon information structure
        /// from client NTLM authenticate response message
        /// </summary>
        /// <param name="parameterControl">
        /// A set of bit flags that contain information pertaining to the logon validation processing.
        /// </param>
        /// <param name="nlmpAuthenticatePacket">
        /// nlmp authenticate response packet sent from client machine
        /// </param>
        /// <param name="lmChallenge">
        /// nlmp challenge sent from server to client
        /// </param>
        /// <returns>
        /// Nlmp pass-through network logon information
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// Thrown when nlmpAuthenticatePacket or lmChallenge is null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Thrown when the length of lmChallenge is not equal to 8 bytes
        /// </exception>
        public static _NETLOGON_LEVEL CreateNlmpNetworkLogonInfo(
            NrpcParameterControlFlags parameterControl,
            NlmpAuthenticatePacket nlmpAuthenticatePacket,
            byte[] lmChallenge
            )
        {
            if (nlmpAuthenticatePacket == null)
            {
                throw new ArgumentNullException("nlmpAuthenticatePacket");
            }

            if (lmChallenge == null)
            {
                throw new ArgumentNullException("lmChallenge");
            }

            // ServerChallenge (8 bytes): A 64-bit value that contains the NTLM challenge.
            // The challenge is a 64-bit nonce. The processing of the
            // ServerChallenge is specified in sections 3.1.5 and 3.2.5.
            if (lmChallenge.Length != NLMP_SERVER_CHALLENGE_LENGTH)
            {
                throw new ArgumentException(
                          "the length of lmChallenge should be 8 bytes",
                          "lmChallenge");
            }

            string domainName;
            string userName;
            string logonWorkStation;

            _NETLOGON_LEVEL netLogonLevel = new _NETLOGON_LEVEL();

            if (nlmpAuthenticatePacket.Payload.DomainName != null)
            {
                domainName = Encoding.Unicode.GetString(nlmpAuthenticatePacket.Payload.DomainName);
            }
            else
            {
                throw new ArgumentException(
                          "DomainName field should not be null",
                          "nlmpAuthenticatePacket");
            }

            if (nlmpAuthenticatePacket.Payload.UserName != null)
            {
                userName = Encoding.Unicode.GetString(nlmpAuthenticatePacket.Payload.UserName);
            }
            else
            {
                throw new ArgumentException(
                          "UserName field should not be null",
                          "nlmpAuthenticatePacket");
            }

            if (nlmpAuthenticatePacket.Payload.Workstation != null)
            {
                logonWorkStation = Encoding.Unicode.GetString(nlmpAuthenticatePacket.Payload.Workstation);
            }
            else
            {
                throw new ArgumentException(
                          "WorkStation field should not be null",
                          "nlmpAuthenticatePacket");
            }

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

            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(nlmpAuthenticatePacket.Payload.LmChallengeResponse);
            netLogonLevel.LogonNetwork[0].NtChallengeResponse =
                NrpcUtility.CreateString(nlmpAuthenticatePacket.Payload.NtChallengeResponse);

            return(netLogonLevel);
        }