/// <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; }
public void APDS_KERBEROS_PAC_VALIDATION() { base.Logging(); BaseTestSite.Log.Add(LogEntryKind.Comment, "Construct Kerberos client for testing."); client = new KerberosTestClient( this.testConfig.LocalRealm.RealmName, this.testConfig.LocalRealm.Admin.Username, this.testConfig.LocalRealm.Admin.Password, KerberosAccountType.User, testConfig.LocalRealm.KDC[0].IPAddress, testConfig.LocalRealm.KDC[0].Port, testConfig.TransportType, testConfig.SupportedOid); BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with no PA data."); KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE; client.SendAsRequest(options, null); //Recieve preauthentication required error METHOD_DATA methodData; KerberosKrbError krbError = client.ExpectPreauthRequiredError(out methodData); //Create sequence of PA data string timeStamp = KerberosUtility.CurrentKerberosTime.Value; PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp, 0, this.client.Context.SelectedEType, this.client.Context.CName.Password, this.client.Context.CName.Salt); PaPacRequest paPacRequest = new PaPacRequest(true); Asn1SequenceOf<PA_DATA> seqOfPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data}); BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with PA data."); client.SendAsRequest(options, seqOfPaData); KerberosAsResponse asResponse = client.ExpectAsResponse(); BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT."); BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send TGS request."); client.SendTgsRequest(this.testConfig.LocalRealm.ClientComputer.DefaultServiceName, options); KerberosTgsResponse tgsResponse = client.ExpectTgsResponse(); EncryptionKey key = testConfig.QueryKey(this.testConfig.LocalRealm.ClientComputer.DefaultServiceName, this.testConfig.LocalRealm.RealmName, this.client.Context.SelectedEType); tgsResponse.DecryptTicket(key); if (this.testConfig.IsKileImplemented) { //Get Server and KDC Signatures PacServerSignature pacServerSignature = null; PacKdcSignature pacKdcSignature = null; BaseTestSite.Assert.IsNotNull(tgsResponse.TicketEncPart.authorization_data, "The ticket contains Authorization data."); AdWin2KPac adWin2kPac = FindOneInAuthData<AdWin2KPac>(tgsResponse.TicketEncPart.authorization_data.Elements); BaseTestSite.Assert.IsNotNull(adWin2kPac, "The Authorization data contains AdWin2KPac."); foreach (var buf in adWin2kPac.Pac.PacInfoBuffers) { if (buf is PacServerSignature) { pacServerSignature = buf as PacServerSignature; } if (buf is PacKdcSignature) { pacKdcSignature = buf as PacKdcSignature; } } BaseTestSite.Log.Add(LogEntryKind.Comment, "Establish Secure Channel."); NrpcClient nrpcClient = NrpcClient.CreateNrpcClient(this.testConfig.LocalRealm.RealmName); ushort[] endPointList = NrpcUtility.QueryNrpcTcpEndpoint(testConfig.LocalRealm.KDC[0].FQDN); ushort endPoint = endPointList[0]; MachineAccountCredential machineCredential = new MachineAccountCredential( this.testConfig.LocalRealm.RealmName, testConfig.LocalRealm.ClientComputer.FQDN.Split('.')[0], testConfig.LocalRealm.ClientComputer.Password); 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( this.testConfig.LocalRealm.RealmName, testConfig.LocalRealm.KDC[0].FQDN.Split('.')[0], machineCredential, true, nrpcClient.Context.NegotiateFlags); nrpcClient.BindOverTcp(testConfig.LocalRealm.KDC[0].FQDN, endPoint, securityContext, TimeSpan.FromMilliseconds(600000)); _NETLOGON_LOGON_INFO_CLASS logonLevel = _NETLOGON_LOGON_INFO_CLASS.NetlogonGenericInformation; _NETLOGON_VALIDATION_INFO_CLASS validationLevel = _NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationGenericInfo2; _NETLOGON_VALIDATION? validationInfomation; byte? authoritative; NrpcNetrLogonSamLogonExtraFlags? extraFlags = NrpcNetrLogonSamLogonExtraFlags.None; BaseTestSite.Log.Add(LogEntryKind.Comment, "Create valid KERB_VERIFY_PAC_REQUEST."); KERB_VERIFY_PAC_REQUEST kerberosReq = ApdsUtility.CreateKerbVerifyPacRequest(pacServerSignature.NativePacSignatureData, pacKdcSignature.NativePacSignatureData); //Create Kerberos Validation Logon Info _NETLOGON_LEVEL netlogonLevel = ApdsUtility.CreatePacLogonInfo( NrpcParameterControlFlags.AllowLogonWithComputerAccount, this.testConfig.LocalRealm.RealmName, this.testConfig.LocalRealm.Admin.Username, testConfig.LocalRealm.KDC[0].FQDN.Split('.')[0], kerberosReq); _NETLOGON_LEVEL encryptedLogonLevel = nrpcClient.EncryptNetlogonLevel( (_NETLOGON_LOGON_INFO_CLASS)logonLevel, netlogonLevel); BaseTestSite.Log.Add(LogEntryKind.Comment, "Call NetrLogonSamLogonEx for Kerberos pac validation."); NtStatus result = nrpcClient.NetrLogonSamLogonEx( nrpcClient.Handle, testConfig.LocalRealm.KDC[0].FQDN.Split('.')[0], testConfig.LocalRealm.ClientComputer.FQDN.Split('.')[0], logonLevel, encryptedLogonLevel, validationLevel, out validationInfomation, out authoritative, ref extraFlags); BaseTestSite.Assert.AreEqual(NtStatus.STATUS_SUCCESS, result, "[MS-APDS]3.2.5.2 If the checksum is verified, the DC MUST return STATUS_SUCCESS."); BaseTestSite.Assert.IsNull(validationInfomation.Value.ValidationGeneric2[0].ValidationData, "[MS-APDS]3.2.5.2 There is no return message."); BaseTestSite.Log.Add(LogEntryKind.Comment, "Create invalid KERB_VERIFY_PAC_REQUEST."); kerberosReq = ApdsUtility.CreateKerbVerifyPacRequest(pacKdcSignature.NativePacSignatureData, pacKdcSignature.NativePacSignatureData); //Create Kerberos Validation Logon Info netlogonLevel = ApdsUtility.CreatePacLogonInfo( NrpcParameterControlFlags.AllowLogonWithComputerAccount, this.testConfig.LocalRealm.RealmName, this.testConfig.LocalRealm.Admin.Username, testConfig.LocalRealm.KDC[0].FQDN.Split('.')[0], kerberosReq); encryptedLogonLevel = nrpcClient.EncryptNetlogonLevel( (_NETLOGON_LOGON_INFO_CLASS)logonLevel, netlogonLevel); BaseTestSite.Log.Add(LogEntryKind.Comment, "Call NetrLogonSamLogonEx for Kerberos pac validation."); result = nrpcClient.NetrLogonSamLogonEx( nrpcClient.Handle, testConfig.LocalRealm.KDC[0].FQDN.Split('.')[0], testConfig.LocalRealm.ClientComputer.FQDN.Split('.')[0], logonLevel, encryptedLogonLevel, validationLevel, out validationInfomation, out authoritative, ref extraFlags); BaseTestSite.Assert.AreEqual(NtStatus.STATUS_LOGON_FAILURE, result, "[MS-APDS]3.2.5.2 If the checksum verification fails, the DC MUST return an error code, STATUS_LOGON_FAILURE (section 2.2) as the return value to the Netlogon Generic Pass-through method."); } }
/// <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; }