/// <summary>
        /// Initialize an instance of NrpcClientSecurityContext class.
        /// By calling this constructor, the class will setup a new secure
        /// channel between client and server.
        /// </summary>
        /// <param name="domainName">
        /// The NRPC domain name.
        /// </param>
        /// <param name="serverName">
        /// The NRPC server name.
        /// </param>
        /// <param name="credential">
        /// The credential to setup the secure channel.
        /// </param>
        /// <param name="requestConfidentiality">
        /// A Boolean setting that indicates that the caller is requiring
        /// encryption of messages so that they cannot be read while in transit.
        /// Requesting this service results in Netlogon encrypting the message.
        /// </param>
        /// <param name="clientCapabilities">
        /// The client capability.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Thrown when domainName, serverName or credential is null.
        /// </exception>
        public NrpcClientSecurityContext(
            string domainName,
            string serverName,
            MachineAccountCredential credential,
            bool requestConfidentiality,
            NrpcNegotiateFlags clientCapabilities)
        {
            if (string.IsNullOrWhiteSpace(domainName))
            {
                throw new ArgumentNullException("domainName cannot be null or empty");
            }
            if (string.IsNullOrWhiteSpace(serverName))
            {
                throw new ArgumentNullException("serverName cannot be null or empty");
            }
            if (credential == null)
            {
                throw new ArgumentNullException("credential cannot be null");
            }

            this.nrpc = NrpcClient.CreateNrpcClient(domainName);
            this.nrpc.Context.PrimaryName       = serverName;
            this.nrpc.Context.SealSecureChannel = requestConfidentiality;
            this.nrpc.Context.NegotiateFlags    = clientCapabilities;

            this.credential        = credential;
            this.secureChannelType = _NETLOGON_SECURE_CHANNEL_TYPE.WorkstationSecureChannel;
        }
        /// <summary>
        /// Initialize an instance of NrpcClientSecurityContext class. 
        /// By calling this constructor, the class will setup a new secure 
        /// channel between client and server.
        /// </summary>
        /// <param name="domainName">
        /// The NRPC domain name.
        /// </param>
        /// <param name="serverName">
        /// The NRPC server name.
        /// </param>
        /// <param name="credential">
        /// The credential to setup the secure channel.
        /// </param>
        /// <param name="requestConfidentiality">
        /// A Boolean setting that indicates that the caller is requiring 
        /// encryption of messages so that they cannot be read while in transit. 
        /// Requesting this service results in Netlogon encrypting the message.
        /// </param>
        /// <param name="clientCapabilities">
        /// The client capability.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Thrown when domainName, serverName or credential is null.
        /// </exception>
        public NrpcClientSecurityContext(
            string domainName,
            string serverName,
            MachineAccountCredential credential,
            bool requestConfidentiality,
            NrpcNegotiateFlags clientCapabilities)
        {
            if (string.IsNullOrWhiteSpace(domainName))
            {
                throw new ArgumentNullException("domainName cannot be null or empty");
            }
            if (string.IsNullOrWhiteSpace(serverName))
            {
                throw new ArgumentNullException("serverName cannot be null or empty");
            }
            if (credential == null)
            {
                throw new ArgumentNullException("credential cannot be null");
            }

            this.nrpc = NrpcClient.CreateNrpcClient(domainName);
            this.nrpc.Context.PrimaryName = serverName;
            this.nrpc.Context.SealSecureChannel = requestConfidentiality;
            this.nrpc.Context.NegotiateFlags = clientCapabilities;

            this.credential = credential;
            this.secureChannelType = _NETLOGON_SECURE_CHANNEL_TYPE.WorkstationSecureChannel;
        }
 /// <summary>
 /// Initializes a new instance of the NrpcCustomClientSecurityContext class. By calling this constructor,
 /// the class will setup a new secure channel between client and server.
 /// </summary>
 /// <param name="domainName">The NRPC domain name.</param>
 /// <param name="serverName"> The NRPC server name.</param>
 /// <param name="credential">The credential to setup the secure channel.</param>
 /// <param name="requestConfidentiality">A Boolean setting that indicates that the caller is requiring
 /// encryption of messages so that they cannot be read while in transit.
 ///  Requesting this service results in Netlogon encrypting the message.</param>
 /// <param name="clientCapabilities">The client capability.</param>
 public NrpcCustomClientSecurityContext(
     string domainName,
     string serverName,
     MachineAccountCredential credential,
     bool requestConfidentiality,
     NrpcNegotiateFlags clientCapabilities)
     : base(domainName, serverName, credential, requestConfidentiality, clientCapabilities)
 {
 }
        /// <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.");
                }
            }
        }
 /// <summary>
 /// Initialize an instance of NrpcClientSecurityContext class.
 /// By calling this constructor, the class will setup a new secure
 /// channel between client and server.
 /// </summary>
 /// <param name="domainName">
 /// The NRPC domain name.
 /// </param>
 /// <param name="serverName">
 /// The NRPC server name.
 /// </param>
 /// <param name="credential">
 /// The credential to setup the secure channel.
 /// </param>
 /// <param name="requestConfidentiality">
 /// A Boolean setting that indicates that the caller is requiring
 /// encryption of messages so that they cannot be read while in transit.
 /// Requesting this service results in Netlogon encrypting the message.
 /// </param>
 /// <param name="clientCapabilities">
 /// The client capability.
 /// </param>
 /// <param name="secureChannelType">
 /// the type of secure channel to use in a logon transaction.
 /// </param>
 /// <exception cref="ArgumentNullException">
 /// Thrown when domainName, serverName or credential is null.
 /// </exception>
 public NrpcClientSecurityContext(
     string domainName,
     string serverName,
     MachineAccountCredential credential,
     bool requestConfidentiality,
     NrpcNegotiateFlags clientCapabilities,
     _NETLOGON_SECURE_CHANNEL_TYPE secureChannelType
     )
     : this(domainName,
            serverName,
            credential,
            requestConfidentiality,
            clientCapabilities)
 {
     this.secureChannelType = secureChannelType;
 }
 /// <summary>
 /// Initialize an instance of NrpcClientSecurityContext class. 
 /// By calling this constructor, the class will setup a new secure 
 /// channel between client and server.
 /// </summary>
 /// <param name="domainName">
 /// The NRPC domain name.
 /// </param>
 /// <param name="serverName">
 /// The NRPC server name.
 /// </param>
 /// <param name="credential">
 /// The credential to setup the secure channel.
 /// </param>
 /// <param name="requestConfidentiality">
 /// A Boolean setting that indicates that the caller is requiring 
 /// encryption of messages so that they cannot be read while in transit. 
 /// Requesting this service results in Netlogon encrypting the message.
 /// </param>
 /// <param name="clientCapabilities">
 /// The client capability.
 /// </param>
 /// <param name="secureChannelType">
 /// the type of secure channel to use in a logon transaction.
 /// </param>
 /// <exception cref="ArgumentNullException">
 /// Thrown when domainName, serverName or credential is null.
 /// </exception>
 public NrpcClientSecurityContext(
     string domainName,
     string serverName,
     MachineAccountCredential credential,
     bool requestConfidentiality,
     NrpcNegotiateFlags clientCapabilities,
     _NETLOGON_SECURE_CHANNEL_TYPE secureChannelType
     )
     : this(domainName,
       serverName,
       credential,
       requestConfidentiality,
       clientCapabilities)
 {
     this.secureChannelType = secureChannelType;
 }
Ejemplo n.º 7
0
        /// <summary>
        ///  The NetrServerAuthenticate3 method mutually authenticates
        ///  the client and the server and establishes the session
        ///  key to be used for the secure channel message protection
        ///  between the client and the server. Supported in windows_2000_server,
        ///  windows_xp, windows_server_2003, windows_vista, windows_server_2008,
        ///  windows_7, and windows_server_7. It is called after
        ///  the NetrServerReqChallenge method.
        ///  Opnum: 26 
        /// </summary>
        /// <param name="primaryName">
        ///  The custom RPC binding handle.
        /// </param>
        /// <param name="accountName">
        ///  A null-terminated Unicode string that identifies the
        ///  name of the account that contains the secret key (password)
        ///  that is shared between the client and the server. 
        ///  In windows, all machine account
        ///  names are the name of the machine with a $ (dollar
        ///  sign) appended. If there is a period at the end of
        ///  the account name, it is ignored during processing.
        /// </param>
        /// <param name="secureChannelType">
        ///  A NETLOGON_SECURE_CHANNEL_TYPE enumerated value, 
        ///  that indicates the type of the
        ///  secure channel being established by this call.
        /// </param>
        /// <param name="computerName">
        ///  A null-terminated Unicode string that contains the NetBIOS
        ///  name of the client computer calling this method.
        /// </param>
        /// <param name="clientCredential">
        ///  A pointer to a NETLOGON_CREDENTIAL structure, 
        ///  that contains the supplied client credentials.
        /// </param>
        /// <param name="serverCredential">
        ///  A pointer to a NETLOGON_CREDENTIAL structure, 
        ///  that contains the returned server credentials.
        /// </param>
        /// <param name="negotiateFlags">
        ///  A pointer to a 32-bit set of bit flags that indicate
        ///  features supported. As input, the set of flags are
        ///  those requested by the client and SHOULD be the same
        ///  as ClientCapabilities. As output, they are the bit-wise
        ///  AND of the client's requested capabilities and the
        ///  server's ServerCapabilities.
        /// </param>
        /// <param name="accountRid">
        ///  A pointer that receives the RID of the account specified
        ///  by the AccountName parameter. ([MS-ADTS]
        ///  describes how this RID is assigned at account creation
        ///  time.) This value is stored in the AccountRid ADM element
        ///  within the ClientSessionInfo table.
        /// </param>
        /// <returns>
        /// The method returns 0x00000000 on success; 
        /// otherwise, it returns a nonzero error code.
        /// </returns>
        public NtStatus NetrServerAuthenticate3(
            string primaryName,
            string accountName,
            _NETLOGON_SECURE_CHANNEL_TYPE secureChannelType,
            string computerName,
            _NETLOGON_CREDENTIAL? clientCredential,
            out _NETLOGON_CREDENTIAL? serverCredential,
            ref NrpcNegotiateFlags? negotiateFlags,
            out uint? accountRid)
        {
            context.PrimaryName = primaryName;
            context.AccountName = accountName;
            context.SecureChannelType = secureChannelType;
            context.ClientComputerName = computerName;
            if (clientCredential != null)
            {
                context.StoredCredential = clientCredential.Value.data;
            }
            if (negotiateFlags != null)
            {
                context.NegotiateFlags = (NrpcNegotiateFlags)negotiateFlags.Value;
            }

            uint? flags = (uint?)negotiateFlags;

            NtStatus status = rpc.NetrServerAuthenticate3(
                primaryName,
                accountName,
                secureChannelType,
                computerName,
                clientCredential,
                out serverCredential,
                ref flags,
                out accountRid);

            context.ConnectionStatus = status;
            if (status == NtStatus.STATUS_SUCCESS)
            {
                negotiateFlags = (NrpcNegotiateFlags?)flags;
                if (negotiateFlags != null)
                {
                    context.NegotiateFlags = (NrpcNegotiateFlags)negotiateFlags.Value;
                }
                if (accountRid != null)
                {
                    context.AccountRid = accountRid.Value;
                }
                if (context.SessionKey == null
                    && context.SharedSecret != null
                    && context.ClientChallenge != null
                    && context.ServerChallenge != null)
                {
                    if ((context.NegotiateFlags & NrpcNegotiateFlags.SupportsAESAndSHA2) != 0)
                    {
                        context.SessionKey = NrpcUtility.ComputeSessionKey(
                            NrpcComputeSessionKeyAlgorithm.HMACSHA256,
                            context.SharedSecret,
                            context.ClientChallenge,
                            context.ServerChallenge);
                    }
                    else if ((context.NegotiateFlags & NrpcNegotiateFlags.SupportsStrongKeys) != 0)
                    {
                        context.SessionKey = NrpcUtility.ComputeSessionKey(
                            NrpcComputeSessionKeyAlgorithm.MD5,
                            context.SharedSecret,
                            context.ClientChallenge,
                            context.ServerChallenge);
                    }
                    else
                    {
                        context.SessionKey = NrpcUtility.ComputeSessionKey(
                            NrpcComputeSessionKeyAlgorithm.DES,
                            context.SharedSecret,
                            context.ClientChallenge,
                            context.ServerChallenge);
                    }
                }
            }

            return status;
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Call NetrServerAuthenticate3, get necessary information from context.
        /// </summary>
        /// <param name="accountName">
        /// A null-terminated Unicode string that identifies the name of 
        /// the account that contains the secret key (password) that is shared 
        /// between the client and the server.
        /// </param>
        /// <param name="secureChannelType">
        /// A NETLOGON_SECURE_CHANNEL_TYPE enumerated value, 
        /// that indicates the type of the
        /// secure channel being established by this call.
        /// </param>
        /// <param name="clientCapabilities">
        /// A pointer to a 32-bit set of bit flags in little-endian format that 
        /// indicate features supported. As input, the set of flags are those 
        /// requested by the client and SHOULD be the same as ClientCapabilities. 
        /// As output, they are the bit-wise AND of the client's requested capabilities 
        /// and the server's ServerCapabilities.
        /// </param>
        /// <param name="sharedSecret">
        /// An even-numbered sequence of bytes, with no embedded zero values, 
        /// that is a plain-text secret (password) shared between the client and the server.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Thrown when account or sharedSecret is null.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Thrown when server returned an error code or 
        /// server returned credential validation failed.
        /// </exception>
        public void NetrServerAuthenticate3(
            string accountName,
            _NETLOGON_SECURE_CHANNEL_TYPE secureChannelType,
            ref NrpcNegotiateFlags clientCapabilities,
            string sharedSecret)
        {
            if (accountName == null)
            {
                throw new ArgumentNullException("accountName");
            }
            if (sharedSecret == null)
            {
                throw new ArgumentNullException("sharedSecret");
            }

            context.SharedSecret = sharedSecret;

            NrpcComputeSessionKeyAlgorithm computeSessionKeyAlgorithm;
            NrpcComputeNetlogonCredentialAlgorithm computeNetlogonCredentialAlgorithm;

            if ((clientCapabilities & NrpcNegotiateFlags.SupportsAESAndSHA2) ==
                NrpcNegotiateFlags.SupportsAESAndSHA2)
            {
                computeSessionKeyAlgorithm = NrpcComputeSessionKeyAlgorithm.HMACSHA256;
                computeNetlogonCredentialAlgorithm = NrpcComputeNetlogonCredentialAlgorithm.AES128;
            }
            else if ((clientCapabilities & NrpcNegotiateFlags.SupportsStrongKeys) ==
                NrpcNegotiateFlags.SupportsStrongKeys)
            {
                computeSessionKeyAlgorithm = NrpcComputeSessionKeyAlgorithm.MD5;
                computeNetlogonCredentialAlgorithm = NrpcComputeNetlogonCredentialAlgorithm.DESECB;
            }
            else
            {
                computeSessionKeyAlgorithm = NrpcComputeSessionKeyAlgorithm.DES;
                computeNetlogonCredentialAlgorithm = NrpcComputeNetlogonCredentialAlgorithm.DESECB;
            }

            context.SessionKey = NrpcUtility.ComputeSessionKey(
                computeSessionKeyAlgorithm,
                context.SharedSecret,
                context.ClientChallenge,
                context.ServerChallenge);

            _NETLOGON_CREDENTIAL clientCredential = new _NETLOGON_CREDENTIAL();
            clientCredential.data = NrpcUtility.ComputeNetlogonCredential(
                computeNetlogonCredentialAlgorithm,
                context.ClientChallenge,
                context.SessionKey);

            _NETLOGON_CREDENTIAL? serverCredential;

            NrpcNegotiateFlags? flags = clientCapabilities;
            uint? accountRid;

            NtStatus status = NetrServerAuthenticate3(
                context.PrimaryName,
                accountName,
                secureChannelType,
                context.ClientComputerName,
                clientCredential,
                out serverCredential,
                ref flags,
                out accountRid);

            if (status != NtStatus.STATUS_SUCCESS)
            {
                NrpcUtility.ThrowExceptionOnStatus("NetrServerAuthenticate3", (int)status);
            }
            if (serverCredential == null
                || !ArrayUtility.CompareArrays(
                    serverCredential.Value.data,
                    NrpcUtility.ComputeNetlogonCredential(
                        computeNetlogonCredentialAlgorithm,
                        context.ServerChallenge,
                        context.SessionKey)))
            {
                NrpcUtility.ThrowExceptionOnValidationFail("NetrServerAuthenticate3");
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        ///  The NetrServerAuthenticate2 method This method was used
        ///  in windows_nt_3_5 and windows_nt_4_0. In windows_2000_server,
        ///  windows_xp, windows_server_2003, windows_vista, windows_server_2008,
        ///  windows_7, and windows_server_7, it was superseded
        ///  by the NetrServerAuthenticate3 method. is
        ///  a predecessor to the NetrServerAuthenticate3 method. 
        ///  All parameters of this method
        ///  have the same meanings as the identically named parameters
        ///  of the NetrServerAuthenticate3 method. Opnum: 15 
        /// </summary>
        /// <param name="primaryName">
        ///  PrimaryName parameter.
        /// </param>
        /// <param name="accountName">
        ///  AccountName parameter.
        /// </param>
        /// <param name="secureChannelType">
        ///  SecureChannelType parameter.
        /// </param>
        /// <param name="computerName">
        ///  ComputerName parameter.
        /// </param>
        /// <param name="clientCredential">
        ///  ClientCredential parameter.
        /// </param>
        /// <param name="serverCredential">
        ///  ServerCredential parameter.
        /// </param>
        /// <param name="negotiateFlags">
        ///  NegotiateFlags parameter.
        /// </param>
        /// <returns>
        /// The method returns 0x00000000 on success; 
        /// otherwise, it returns a nonzero error code.
        /// </returns>
        public NtStatus NetrServerAuthenticate2(
            string primaryName,
            string accountName,
            _NETLOGON_SECURE_CHANNEL_TYPE secureChannelType,
            string computerName,
            _NETLOGON_CREDENTIAL? clientCredential,
            out _NETLOGON_CREDENTIAL? serverCredential,
            ref NrpcNegotiateFlags? negotiateFlags)
        {
            uint? flags = (uint?)negotiateFlags;

            NtStatus status = rpc.NetrServerAuthenticate2(
                primaryName,
                accountName,
                secureChannelType,
                computerName,
                clientCredential,
                out serverCredential,
                ref flags);

            context.ConnectionStatus = status;
            negotiateFlags = (NrpcNegotiateFlags?)flags;
            return status;
        }