/// <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, as specified in /// section. Opnum: 26 /// </summary> /// <param name="PrimaryName"> /// The custom RPC binding handle, as specified in section /// . /// </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, as /// specified in section.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, as /// specified in section , 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, as specified /// in section , that contains the supplied client credentials, /// as specified in section. /// </param> /// <param name="ServerCredential"> /// A pointer to a NETLOGON_CREDENTIAL structure, as specified /// in section , 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. For more details, see /// section. /// </param> /// <param name="AccountRid"> /// A pointer that receives the RID of the account specified /// by the AccountName parameter. (Section of [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> public NtStatus NetrServerAuthenticate3( string PrimaryName, string AccountName, _NETLOGON_SECURE_CHANNEL_TYPE SecureChannelType, string ComputerName, _NETLOGON_CREDENTIAL? ClientCredential, out _NETLOGON_CREDENTIAL? ServerCredential, ref uint? NegotiateFlags, out uint? AccountRid) { const ushort opnum = 26; byte[] requestStub; byte[] responseStub; Int3264[] paramList; int retVal; SafeIntPtr pPrimaryName = Marshal.StringToHGlobalUni(PrimaryName); SafeIntPtr pAccountName = Marshal.StringToHGlobalUni(AccountName); SafeIntPtr pComputerName = Marshal.StringToHGlobalUni(ComputerName); SafeIntPtr pClientCredential = TypeMarshal.ToIntPtr(ClientCredential); SafeIntPtr pNegotiateFlags = TypeMarshal.ToIntPtr(NegotiateFlags); paramList = new Int3264[] { pPrimaryName, pAccountName, (uint)SecureChannelType, pComputerName, pClientCredential, IntPtr.Zero, pNegotiateFlags, IntPtr.Zero, 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 pServerCredential = outParamList[5]; ServerCredential = TypeMarshal.ToNullableStruct<_NETLOGON_CREDENTIAL>(pServerCredential); NegotiateFlags = TypeMarshal.ToNullableStruct<uint>(outParamList[6]); AccountRid = TypeMarshal.ToNullableStruct<uint>(outParamList[7]); retVal = outParamList[8].ToInt32(); } pPrimaryName.Dispose(); pAccountName.Dispose(); pComputerName.Dispose(); pClientCredential.Dispose(); pNegotiateFlags.Dispose(); return (NtStatus)retVal; }
/// <summary> /// The NetrServerReqChallenge method receives a client /// challenge and returns a server challenge. Opnum: 4 /// /// </summary> /// <param name="PrimaryName"> /// The custom RPC binding handle, as specified in section /// . /// </param> /// <param name="ComputerName"> /// A Unicode string that contains the NetBIOS name of the /// client computer calling this method. /// </param> /// <param name="ClientChallenge"> /// A pointer to a NETLOGON_CREDENTIAL structure, as specified /// in section , that contains the client challenge. /// </param> /// <param name="ServerChallenge"> /// A pointer to a NETLOGON_CREDENTIAL structure, as specified /// in section , that contains the server challenge response. /// </param> public NtStatus NetrServerReqChallenge( string PrimaryName, string ComputerName, _NETLOGON_CREDENTIAL? ClientChallenge, out _NETLOGON_CREDENTIAL? ServerChallenge) { const ushort opnum = 4; byte[] requestStub; byte[] responseStub; Int3264[] paramList; int retVal; SafeIntPtr pPrimaryName = Marshal.StringToHGlobalUni(PrimaryName); SafeIntPtr pComputerName = Marshal.StringToHGlobalUni(ComputerName); SafeIntPtr pClientChallenge = TypeMarshal.ToIntPtr(ClientChallenge); paramList = new Int3264[] { pPrimaryName, pComputerName, pClientChallenge, IntPtr.Zero, 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 pServerChallenge = outParamList[3]; ServerChallenge = TypeMarshal.ToNullableStruct<_NETLOGON_CREDENTIAL>(pServerChallenge); retVal = outParamList[4].ToInt32(); } pPrimaryName.Dispose(); pComputerName.Dispose(); pClientChallenge.Dispose(); return (NtStatus)retVal; }
/// <summary> /// The NetrServerReqChallenge method receives a client /// challenge and returns a server challenge. Opnum: 4<para/> /// </summary> /// <param name="primaryName"> /// The custom RPC binding handle. /// </param> /// <param name="computerName"> /// A Unicode string that contains the NetBIOS name of the /// client computer calling this method. /// </param> /// <param name="clientChallenge"> /// A pointer to a NETLOGON_CREDENTIAL structure, /// that contains the client challenge. /// </param> /// <param name="serverChallenge"> /// A pointer to a NETLOGON_CREDENTIAL structure, /// that contains the server challenge response. /// </param> /// <returns> /// The method returns 0x00000000 on success; /// otherwise, it returns a nonzero error code. /// </returns> public NtStatus NetrServerReqChallenge( string primaryName, string computerName, _NETLOGON_CREDENTIAL? clientChallenge, out _NETLOGON_CREDENTIAL? serverChallenge) { context.PrimaryName = primaryName; context.ClientComputerName = computerName; if (clientChallenge != null) { context.ClientChallenge = clientChallenge.Value.data; } NtStatus status = rpc.NetrServerReqChallenge( primaryName, computerName, clientChallenge, out serverChallenge); context.ConnectionStatus = status; if (status == NtStatus.STATUS_SUCCESS && serverChallenge != null) { context.ServerChallenge = serverChallenge.Value.data; } return status; }
/// <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; }
/// <summary> /// Call NetrServerReqChallenge, get necessary information from context. /// </summary> /// <param name="computerName"> /// A null-terminated Unicode string that contains the NetBIOS name of /// the client computer calling this method. /// </param> /// <exception cref="ArgumentNullException"> /// Thrown when computerName is null. /// </exception> /// <exception cref="InvalidOperationException"> /// Thrown when server returned an error code. /// </exception> public void NetrServerReqChallenge(string computerName) { if (computerName == null) { throw new ArgumentNullException("computerName"); } _NETLOGON_CREDENTIAL clientChallenge = new _NETLOGON_CREDENTIAL(); clientChallenge.data = NrpcUtility.GenerateNonce(NrpcUtility.NL_CREDENTIAL_LENGTH); _NETLOGON_CREDENTIAL? serverChallenge; NtStatus status = NetrServerReqChallenge( context.PrimaryName, computerName, clientChallenge, out serverChallenge); if (status != NtStatus.STATUS_SUCCESS) { NrpcUtility.ThrowExceptionOnStatus("NetrServerReqChallenge", (int)status); } }
/// <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; }
/// <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"); } }
/// <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; }
/// <summary> /// The NetrServerAuthenticate method This method was used /// in windows_nt_server_3_1. In windows_nt_server_3_5, /// it was superseded by the NetrServerAuthenticate2 method. /// In windows_2000_server, windows_xp, windows_server_2003, /// windows_vista, windows_server_2008, windows_7, and /// windows_server_7, the NetrServerAuthenticate2 method /// 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: 5 /// </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> /// <returns> /// The method returns 0x00000000 on success; /// otherwise, it returns a nonzero error code. /// </returns> public NtStatus NetrServerAuthenticate( string primaryName, string accountName, _NETLOGON_SECURE_CHANNEL_TYPE secureChannelType, string computerName, _NETLOGON_CREDENTIAL? clientCredential, out _NETLOGON_CREDENTIAL? serverCredential) { NtStatus status = rpc.NetrServerAuthenticate( primaryName, accountName, secureChannelType, computerName, clientCredential, out serverCredential); context.ConnectionStatus = status; return status; }