/// <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; }
internal void UpdateSessionContextWithMessageSent(NrpcResponseStub messageToSend) { NrpcClientSessionInfo clientSessionInfo; switch (messageToSend.Opnum) { case NrpcMethodOpnums.NetrServerReqChallenge: NrpcNetrServerReqChallengeResponse netrServerReqChallengeResponse = messageToSend as NrpcNetrServerReqChallengeResponse; if (netrServerReqChallengeResponse == null) { throw new InvalidOperationException("messageToSend doesn't match its MethodOpnums"); } ServerChallenge = netrServerReqChallengeResponse.ServerChallenge.Value.data; break; case NrpcMethodOpnums.NetrServerAuthenticate: NrpcNetrServerAuthenticateResponse netrServerAuthenticateResponse = (messageToSend as NrpcNetrServerAuthenticateResponse); if (netrServerAuthenticateResponse == null) { throw new InvalidOperationException("messageToSend doesn't match its MethodOpnums"); } //if authentication is successfully finished, store the secure channel to the session table if (netrServerAuthenticateResponse.Status == NtStatus.STATUS_SUCCESS) { clientSessionInfo.ComputerName = ClientComputerName; clientSessionInfo.AccountRid = AccountRid; clientSessionInfo.NegotiateFlags = NegotiateFlags; clientSessionInfo.SecureChannelType = SecureChannelType; clientSessionInfo.ServerStoredCredential = StoredCredential; clientSessionInfo.SessionKey = SessionKey; clientSessionInfo.SharedSecret = SharedSecret; clientSessionInfo.ClientSequenceNumber = null; clientSessionInfo.ServerSequenceNumber = null; //if this client computer already established a secure channel, remove it first if (clientSessionInfoTable.ContainsKey(ClientComputerName)) { clientSessionInfoTable.Remove(ClientComputerName); } clientSessionInfoTable[ClientComputerName] = clientSessionInfo; } break; case NrpcMethodOpnums.NetrServerAuthenticate2: NrpcNetrServerAuthenticate2Response netrServerAuthenticate2Response = (messageToSend as NrpcNetrServerAuthenticate2Response); if (netrServerAuthenticate2Response == null) { throw new InvalidOperationException("messageToSend doesn't match its MethodOpnums"); } NegotiateFlags = (NrpcNegotiateFlags)netrServerAuthenticate2Response.NegotiateFlags; //if authentication is successfully finished, store the secure channel to the session table if (netrServerAuthenticate2Response.Status == NtStatus.STATUS_SUCCESS) { clientSessionInfo.ComputerName = ClientComputerName; clientSessionInfo.AccountRid = AccountRid; clientSessionInfo.NegotiateFlags = NegotiateFlags; clientSessionInfo.SecureChannelType = SecureChannelType; clientSessionInfo.ServerStoredCredential = StoredCredential; clientSessionInfo.SessionKey = SessionKey; clientSessionInfo.SharedSecret = SharedSecret; clientSessionInfo.ClientSequenceNumber = null; clientSessionInfo.ServerSequenceNumber = null; //if this client computer already established a secure channel, remove it first if (clientSessionInfoTable.ContainsKey(ClientComputerName)) { clientSessionInfoTable.Remove(ClientComputerName); } clientSessionInfoTable[ClientComputerName] = clientSessionInfo; } break; case NrpcMethodOpnums.NetrLogonGetCapabilities: NrpcNetrLogonGetCapabilitiesResponse nrpcNetrLogonGetCapabilitiesResponse = (messageToSend as NrpcNetrLogonGetCapabilitiesResponse); if (nrpcNetrLogonGetCapabilitiesResponse == null) { throw new InvalidOperationException("messageToSend doesn't match its MethodOpnums"); } NegotiateFlags = (NrpcNegotiateFlags)nrpcNetrLogonGetCapabilitiesResponse.ServerCapabilities.Value.ServerCapabilities; break; case NrpcMethodOpnums.NetrServerAuthenticate3: NrpcNetrServerAuthenticate3Response netrServerAuthenticate3Response = (messageToSend as NrpcNetrServerAuthenticate3Response); if (netrServerAuthenticate3Response == null) { throw new InvalidOperationException("messageToSend doesn't match its MethodOpnums"); } NegotiateFlags = (NrpcNegotiateFlags)netrServerAuthenticate3Response.NegotiateFlags; if (netrServerAuthenticate3Response.AccountRid.HasValue) { AccountRid = netrServerAuthenticate3Response.AccountRid.Value; } //if authentication is successfully finished, store the secure channel to the session table if (netrServerAuthenticate3Response.Status == NtStatus.STATUS_SUCCESS) { clientSessionInfo.ComputerName = ClientComputerName; clientSessionInfo.AccountRid = AccountRid; clientSessionInfo.NegotiateFlags = NegotiateFlags; clientSessionInfo.SecureChannelType = SecureChannelType; clientSessionInfo.ServerStoredCredential = StoredCredential; clientSessionInfo.SessionKey = SessionKey; clientSessionInfo.SharedSecret = SharedSecret; clientSessionInfo.ClientSequenceNumber = null; clientSessionInfo.ServerSequenceNumber = null; //if this client computer already established a secure channel, remove it first if (clientSessionInfoTable.ContainsKey(ClientComputerName)) { clientSessionInfoTable.Remove(ClientComputerName); } clientSessionInfoTable[ClientComputerName] = clientSessionInfo; } break; default: break; } }