public void CheckNegotiateContext <T>(T request, Smb2NegotiateResponsePacket response) { if (response.PayLoad.DialectRevision != DialectRevision.Smb311) { return; } if (request is Smb2NegotiateRequestPacket) { Smb2NegotiateRequestPacket smb2Request = request as Smb2NegotiateRequestPacket; // 3.3.5.4: if Dialect is "3.1.1" Then the server MUST build a NegotiateContextList for its negotiate response and check Including below: // 1. The server MUST add an SMB2_PREAUTH_INTEGRITY_CAPABILITIES negotiate context to the response's NegotiateContextList. if (response.NegotiateContext_PREAUTH == null) { Site.Assert.Fail("The server MUST add an SMB2_PREAUTH_INTEGRITY_CAPABILITIES negotiate context to the response's NegotiateContextList."); } // 2. HashAlgorithmCount MUST be set to 1 Site.Assert.AreEqual <int>(1, response.NegotiateContext_PREAUTH.Value.HashAlgorithmCount, "The response's SMB2_PREAUTH_INTEGRITY_CAPABILITIES.HashAlgorithmCount MUST be set to 1"); // 3. SMB2_PREAUTH_INTEGRITY_CAPABILITIES Salt buffer length same as SaltLength Site.Assert.AreEqual <int>(response.NegotiateContext_PREAUTH.Value.SaltLength, response.NegotiateContext_PREAUTH.Value.Salt.Length, "The response's SMB2_PREAUTH_INTEGRITY_CAPABILITIES Salt buffer length must same as SaltLength"); // 4. If client haven't send a negotiate context the server should not response except SMB2_PREAUTH_INTEGRITY_CAPABILITIES if ((smb2Request.NegotiateContext_ENCRYPTION == null) && (response.NegotiateContext_ENCRYPTION != null)) { Site.Assert.Fail("The server Should not response a SMB2_ENCRYPTION_CAPABILITIES as it's not sent in request."); } if ((smb2Request.NegotiateContext_COMPRESSION == null) && (response.NegotiateContext_COMPRESSION != null)) { Site.Assert.Fail("The server Should not response a SMB2_COMPRESSION_CAPABILITIES as it's not sent in request."); } if ((smb2Request.NegotiateContext_SIGNING == null) && (response.NegotiateContext_SIGNING != null)) { Site.Assert.Fail("The server Should not response a SMB2_SIGNING_CAPABILITIES as it's not sent in request."); } if (response.NegotiateContext_ENCRYPTION != null) { Site.Assert.AreEqual <int>(1, response.NegotiateContext_ENCRYPTION.Value.CipherCount, "The response's SMB2_ENCRYPTION_CAPABILITIES.CipherCount MUST be set to 1"); } } else if (request is SmbNegotiateRequestPacket) { Site.Assert.IsNull(response.NegotiateContext_ENCRYPTION, "The server Should not response a SMB2_ENCRYPTION_CAPABILITIES as request is SmbNegotiateRequestPacket."); Site.Assert.IsNull(response.NegotiateContext_COMPRESSION, "The server Should not response a SMB2_COMPRESSION_CAPABILITIES as request is SmbNegotiateRequestPacket."); Site.Assert.IsNull(response.NegotiateContext_SIGNING, "The server Should not response a SMB2_SIGNING_CAPABILITIES as request is SmbNegotiateRequestPacket."); } }
private Smb2Packet DecodeSingleResponsePacket( byte[] messageBytes, bool ignoreCompoundFlag, ulong realSessionId, uint realTreeId, out int consumedLength, out int expectedLength ) { Packet_Header smb2Header; bool isLeaseBreakPacket = false; int offset = 0; smb2Header = TypeMarshal.ToStruct<Packet_Header>(messageBytes, ref offset); if (smb2Header.Command == Smb2Command.OPLOCK_BREAK) { ushort structureSize = TypeMarshal.ToStruct<ushort>(messageBytes, ref offset); if (structureSize == (ushort)OplockLeaseBreakStructureSize.LeaseBreakNotification || structureSize == (ushort)OplockLeaseBreakStructureSize.LeaseBreakResponse || structureSize == 9) // Add this condition temporally to handle LeaseBreakResponse is error response (i.e. structureSize == 9), but this will still hide the condition when OplockBreakResponse is error response { isLeaseBreakPacket = true; } } Smb2SinglePacket packet = null; ushort structSize = BitConverter.ToUInt16(messageBytes, Smb2Consts.Smb2HeaderLen); switch (smb2Header.Command) { case Smb2Command.CANCEL: packet = new Smb2CancelResponsePacket(); break; case Smb2Command.CHANGE_NOTIFY: packet = new Smb2ChangeNotifyResponsePacket(); break; case Smb2Command.CLOSE: packet = new Smb2CloseResponsePacket(); break; case Smb2Command.CREATE: packet = new Smb2CreateResponsePacket(); break; case Smb2Command.ECHO: packet = new Smb2EchoResponsePacket(); break; case Smb2Command.FLUSH: packet = new Smb2FlushResponsePacket(); break; case Smb2Command.IOCTL: packet = new Smb2IOCtlResponsePacket(); break; case Smb2Command.LOCK: packet = new Smb2LockResponsePacket(); break; case Smb2Command.LOGOFF: packet = new Smb2LogOffResponsePacket(); break; case Smb2Command.NEGOTIATE: packet = new Smb2NegotiateResponsePacket(); break; case Smb2Command.OPLOCK_BREAK: if (smb2Header.MessageId == ulong.MaxValue) { if (!isLeaseBreakPacket) { packet = new Smb2OpLockBreakNotificationPacket(); } else { packet = new Smb2LeaseBreakNotificationPacket(); } } else { if (!isLeaseBreakPacket) { packet = new Smb2OpLockBreakResponsePacket(); } else { packet = new Smb2LeaseBreakResponsePacket(); } } break; case Smb2Command.QUERY_DIRECTORY: packet = new Smb2QueryDirectoryResponePacket(); break; case Smb2Command.QUERY_INFO: packet = new Smb2QueryInfoResponsePacket(); break; case Smb2Command.READ: packet = new Smb2ReadResponsePacket(); break; case Smb2Command.SESSION_SETUP: packet = new Smb2SessionSetupResponsePacket(); break; case Smb2Command.SET_INFO: packet = new Smb2SetInfoResponsePacket(); break; case Smb2Command.TREE_CONNECT: packet = new Smb2TreeConnectResponsePacket(); break; case Smb2Command.TREE_DISCONNECT: packet = new Smb2TreeDisconnectResponsePacket(); break; case Smb2Command.WRITE: packet = new Smb2WriteResponsePacket(); break; default: throw new InvalidOperationException("Received an unknown packet! the type of the packet is " + smb2Header.Command.ToString()); } if (IsErrorPacket(smb2Header)) { var error = new Smb2ErrorResponsePacket(); error.FromBytes(messageBytes, out consumedLength, out expectedLength); packet.Header = error.Header; packet.Error = error; } else { packet.FromBytes(messageBytes, out consumedLength, out expectedLength); } //if ignoreCompoundFlag is false, means the process of decoding this packet //is not part of the process of decoding a compound packet. We will update //context here. if (!ignoreCompoundFlag) { // TODO } return packet; }
public Smb2NegotiateResponsePacket CreateNegotiateResponse( Smb2Endpoint endpoint, DialectRevision_Values dialectRevision, SecurityPackage securityPackage, ServerContextAttribute contextAttribute ) { Smb2NegotiateResponsePacket packet = new Smb2NegotiateResponsePacket(); SetHeader(packet, endpoint, 0); packet.PayLoad.SecurityMode |= NEGOTIATE_Response_SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED; if (context.requireMessageSigning) { packet.PayLoad.SecurityMode |= NEGOTIATE_Response_SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED; } packet.PayLoad.StructureSize = NEGOTIATE_Response_StructureSize_Values.V1; packet.PayLoad.DialectRevision = dialectRevision; packet.PayLoad.ServerGuid = context.serverGuid; if (context.isDfsCapable) { packet.PayLoad.Capabilities |= NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_DFS; } packet.PayLoad.MaxTransactSize = uint.MaxValue; packet.PayLoad.MaxWriteSize = uint.MaxValue; packet.PayLoad.MaxReadSize = uint.MaxValue; packet.PayLoad.SystemTime = Smb2Utility.DateTimeToFileTime(DateTime.Now); packet.PayLoad.ServerStartTime = Smb2Utility.DateTimeToFileTime(context.serverStartTime); SecurityPackageType package = SecurityPackageType.Negotiate; if (securityPackage == SecurityPackage.Kerberos) { package = SecurityPackageType.Kerberos; } else if (securityPackage == SecurityPackage.Nlmp) { package = SecurityPackageType.Ntlm; } AccountCredential credential = new AccountCredential(null, null, null); context.connectionList[endpoint.EndpointId].credential = credential; context.connectionList[endpoint.EndpointId].packageType = package; context.connectionList[endpoint.EndpointId].contextAttribute = (ServerSecurityContextAttribute)contextAttribute; if (package == SecurityPackageType.Negotiate) { context.connectionList[endpoint.EndpointId].gss = new SspiServerSecurityContext( package, credential, null, context.connectionList[endpoint.EndpointId].contextAttribute, SecurityTargetDataRepresentation.SecurityNativeDrep); //Generate the first token context.connectionList[endpoint.EndpointId].gss.Accept(null); packet.PayLoad.Buffer = context.connectionList[endpoint.EndpointId].gss.Token; packet.PayLoad.SecurityBufferOffset = Smb2Consts.SecurityBufferOffsetInNegotiateResponse; } else { packet.PayLoad.Buffer = new byte[0]; } packet.PayLoad.SecurityBufferLength = (ushort)packet.PayLoad.Buffer.Length; packet.Sign(); return packet; }