public void NegotiateRequest(ModelDialectRevision maxSmbVersionClientSupported, SigningFlagType signingFlagType, SigningEnabledType signingEnabledType, SigningRequiredType signingRequiredType) { testClient = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); testClient.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress); DialectRevision[] dialects = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(maxSmbVersionClientSupported)); Packet_Header_Flags_Values headerFlags = (signingFlagType == SigningFlagType.SignedFlagSet) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE; SigningEnabledType resSigningEnabledType = SigningEnabledType.SigningEnabledNotSet; SigningRequiredType resSigningRequiredType = SigningRequiredType.SigningRequiredNotSet; uint status = testClient.Negotiate( headerFlags, dialects, GetNegotiateSecurityMode(signingEnabledType, signingRequiredType), checker: (header, response) => { resSigningEnabledType = response.SecurityMode.HasFlag(NEGOTIATE_Response_SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED) ? SigningEnabledType.SigningEnabledSet : SigningEnabledType.SigningEnabledNotSet; resSigningRequiredType = response.SecurityMode.HasFlag(NEGOTIATE_Response_SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED) ? SigningRequiredType.SigningRequiredSet : SigningRequiredType.SigningRequiredNotSet; }); NegotiateResponse((ModelSmb2Status)status, resSigningEnabledType, resSigningRequiredType, signingConfig); }
public void TreeConnectRequest(SigningFlagType signingFlagType) { uint treeId; SigningModelSessionId modelSessionId = SigningModelSessionId.ZeroSessionId; SigningFlagType responseSigningFlagType = SigningFlagType.SignedFlagNotSet; string sharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare); Packet_Header_Flags_Values headerFlags = (signingFlagType == SigningFlagType.SignedFlagSet) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE; // Inform SDK to disable/enable signing according to SigningFlagType. bool isEnableSigning = !(signingFlagType == SigningFlagType.SignedFlagNotSet); testClient.EnableSessionSigningAndEncryption(enableSigning: isEnableSigning, enableEncryption: false); uint status = testClient.TreeConnect( headerFlags, sharePath, out treeId, checker: (header, response) => { modelSessionId = GetModelSessionId(header.SessionId); responseSigningFlagType = GetSigningFlagType(header.Flags); }); TreeConnectResponse((ModelSmb2Status)status, modelSessionId, responseSigningFlagType); }
private void LogOffSession(Smb2Client client, Packet_Header_Flags_Values packetHeader, ulong messageId, ulong sessionId, uint treeId, FILEID fileId) { if (fileId.Persistent != 0 || fileId.Volatile != 0) { client.Close( 1, 1, packetHeader, messageId++, sessionId, treeId, fileId, Flags_Values.NONE, out _, out _); } client.TreeDisconnect( 1, 1, packetHeader, messageId++, sessionId, treeId, out _, out _); client.LogOff( 1, 1, packetHeader, messageId++, sessionId, out _, out _); }
private uint SessionSetup( Packet_Header_Flags_Values headerFlags, SESSION_SETUP_Request_Flags sessionSetupFlags, SESSION_SETUP_Request_SecurityMode_Values securityMode, SESSION_SETUP_Request_Capabilities_Values capabilities, ulong previousSessionId, SecurityPackageType securityPackageType, string serverName, byte[] token, out byte[] serverGssToken, ushort creditRequest = 64) { Packet_Header header; SESSION_SETUP_Response sessionSetupResponse; uint status; status = client.SessionSetup( 1, creditRequest, headerFlags, messageId++, sessionId, sessionSetupFlags, securityMode, capabilities, previousSessionId, token, out sessionId, out serverGssToken, out header, out sessionSetupResponse); return(status); }
/// <summary> /// This method will send ComNegotiate request before sending a Negotiate request to simulate windows client behaviour. /// If ComNegotiate failed, the Negotiate request will still be sent. /// </summary> public uint MultiProtocolNegotiate( Smb2Client client, ushort creditCharge, ushort creditRequest, Packet_Header_Flags_Values flags, ulong messageId, DialectRevision[] dialects, SecurityMode_Values securityMode, Capabilities_Values capabilities, Guid clientGuid, out DialectRevision selectedDialect, out byte[] gssToken, out Packet_Header responseHeader, out NEGOTIATE_Response responsePayload) { uint status = client.MultiProtocolNegotiate( new string[] { "SMB 2.002", "SMB 2.???" }, out selectedDialect, out gssToken, out responseHeader, out responsePayload); if (responseHeader.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("ComNegotiate", responseHeader.Status); } PreauthIntegrityHashID[] preauthHashAlgs = null; EncryptionAlgorithm[] encryptionAlgs = null; // For back compatibility, if dialects contains SMB 3.11, preauthentication integrity context should be present. if (Array.IndexOf(dialects, DialectRevision.Smb311) >= 0) { preauthHashAlgs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 }; encryptionAlgs = new EncryptionAlgorithm[] { EncryptionAlgorithm.ENCRYPTION_AES128_GCM, EncryptionAlgorithm.ENCRYPTION_AES128_CCM }; } status = client.Negotiate( creditCharge, creditRequest, flags, messageId, dialects, securityMode, capabilities, clientGuid, out selectedDialect, out gssToken, out responseHeader, out responsePayload, 0, preauthHashAlgs, encryptionAlgs); return(status); }
private void SendIoctlPayload( Smb2Client client, CtlCode_Values code, byte[] payload, Packet_Header_Flags_Values headerFlags, ulong messageId, uint treeId, ulong sessionId, FILEID fileId) { if (client == null) { throw new InvalidOperationException("The transport is not connected."); } if (payload == null) { throw new ArgumentNullException("payload"); } var request = new Smb2IOCtlRequestPacket(); request.Header.CreditCharge = 1; request.Header.Command = Smb2Command.IOCTL; request.Header.CreditRequestResponse = 1; request.Header.Flags = headerFlags; request.Header.MessageId = messageId; request.Header.TreeId = treeId; request.Header.SessionId = sessionId; request.PayLoad.CtlCode = code; if (code == CtlCode_Values.FSCTL_DFS_GET_REFERRALS || code == CtlCode_Values.FSCTL_DFS_GET_REFERRALS_EX) { request.PayLoad.FileId = FILEID.Invalid; } else { request.PayLoad.FileId = fileId; } if (payload.Length > 0) { request.PayLoad.InputOffset = request.BufferOffset; request.PayLoad.InputCount = (ushort)payload.Length; request.Buffer = payload; } request.PayLoad.MaxInputResponse = 0; request.PayLoad.MaxOutputResponse = 4096; request.PayLoad.Flags = IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL; ioctlRequestMessageIds.Enqueue(request.Header.MessageId); client.SendPacket(request); }
private SigningFlagType GetSigningFlagType(Packet_Header_Flags_Values flags) { SigningFlagType signingFlag; if (flags.HasFlag(Packet_Header_Flags_Values.FLAGS_SIGNED)) { signingFlag = SigningFlagType.SignedFlagSet; } else { signingFlag = SigningFlagType.SignedFlagNotSet; } return(signingFlag); }
public uint Create( uint treeId, string fileName, CreateOptions_Values createOptions, out FILEID fileId, out Smb2CreateContextResponse[] serverCreateContexts, RequestedOplockLevel_Values requestedOplockLevel_Values = RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, Smb2CreateContextRequest[] createContexts = null, Packet_Header_Flags_Values headerFlag = Packet_Header_Flags_Values.FLAGS_SIGNED, AccessMask accessMask = AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE, ShareAccess_Values shareAccess = ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE | ShareAccess_Values.FILE_SHARE_DELETE, ResponseChecker <CREATE_Response> checker = null, ushort creditRequest = 64) { Packet_Header header; CREATE_Response createResponse; uint status = client.Create( 1, creditRequest, headerFlag, messageId++, sessionId, treeId, fileName, accessMask, shareAccess, createOptions, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, requestedOplockLevel_Values, createContexts, out fileId, out serverCreateContexts, out header, out createResponse); InnerResponseChecker(checker, header, createResponse); grantedCredit = header.CreditRequestResponse; return(status); }
/// <summary> /// Send an SMB2 SESSION_SETUP request with specified parameters /// </summary> /// <param name="headerFlags">A Flags field indicates how to process the operation.</param> /// <param name="sessionSetupFlags">To bind an existing session to a new connection,set to SMB2_SESSION_FLAG_BINDING to bind; otherwise set it to NONE.</param> /// <param name="securityMode">The security mode field specifies whether SMB signing is enabled, required at the server, or both</param> /// <param name="capabilities">Specifies protocol capabilities for the client.</param> /// <param name="token">Gss token to send</param> /// <param name="serverToken">GssToken returned from server</param> /// <param name="isResponseEncryptedSessionFlag">check if SESSION_FLAG_ENCRYPT_DATA returned from server</param> /// <param name="creditRequest">The number of credits the client is requesting. Default value is 64.</param> /// <param name="previousSessionId">For reconnect, set it to previous sessionId, otherwise set it to 0. Default value is 0.</param> /// <returns>The status code for SESSION_SETUP Response.</returns> public uint SessionSetup( Packet_Header_Flags_Values headerFlags, SESSION_SETUP_Request_Flags sessionSetupFlags, SESSION_SETUP_Request_SecurityMode_Values securityMode, SESSION_SETUP_Request_Capabilities_Values capabilities, byte[] token, out byte[] serverToken, out bool isResponseEncryptedSessionFlag, ushort creditRequest = 64, ulong previousSessionId = 0) { Packet_Header header; SESSION_SETUP_Response sessionSetupResponse; ulong messageId = generateMessageId(sequenceWindow); ushort creditCharge = generateCreditCharge(1); // Need to consume credit from sequence window first according to TD ConsumeCredit(messageId, creditCharge); uint status = Smb2Client.SessionSetup( 1, creditRequest, headerFlags, messageId, sessionId, sessionSetupFlags, securityMode, capabilities, previousSessionId, token, out sessionId, out serverToken, out header, out sessionSetupResponse); isResponseEncryptedSessionFlag = sessionSetupResponse.SessionFlags.HasFlag(SessionFlags_Values.SESSION_FLAG_ENCRYPT_DATA); ProduceCredit(messageId, header); return(status); }
/// <summary> /// Send an SMB2 SESSION_SETUP request with specified parameters /// </summary> /// <param name="headerFlags">A Flags field indicates how to process the operation.</param> /// <param name="sessionSetupFlags">To bind an existing session to a new connection,set to SMB2_SESSION_FLAG_BINDING to bind; otherwise set it to NONE.</param> /// <param name="securityMode">The security mode field specifies whether SMB signing is enabled, required at the server, or both</param> /// <param name="capabilities">Specifies protocol capabilities for the client.</param> /// <param name="token">Gss token to send</param> /// <param name="serverToken">GssToken returned from server</param> /// <param name="creditRequest">The number of credits the client is requesting. Default value is 64.</param> /// <param name="previousSessionId">For reconnect, set it to previous sessionId, otherwise set it to 0. Default value is 0.</param> /// <returns>The status code for SESSION_SETUP Response.</returns> public uint SessionSetup( Packet_Header_Flags_Values headerFlags, SESSION_SETUP_Request_Flags sessionSetupFlags, SESSION_SETUP_Request_SecurityMode_Values securityMode, SESSION_SETUP_Request_Capabilities_Values capabilities, byte[] token, out byte[] serverToken, ushort creditRequest = 64, ulong previousSessionId = 0) { Packet_Header header; SESSION_SETUP_Response sessionSetupResponse; ulong messageId = generateMessageId(sequenceWindow); ushort creditCharge = generateCreditCharge(1); // Need to consume credit from sequence window first according to TD ConsumeCredit(messageId, creditCharge); uint status = Smb2Client.SessionSetup( 1, creditRequest, headerFlags, messageId, sessionId, sessionSetupFlags, securityMode, capabilities, previousSessionId, token, out sessionId, out serverToken, out header, out sessionSetupResponse); ProduceCredit(messageId, header); return status; }
public void SessionSetupRequest(SigningFlagType signingFlagType, SigningEnabledType signingEnabledType, SigningRequiredType signingRequiredType, UserType userType) { SigningModelSessionId modelSessionId = SigningModelSessionId.ZeroSessionId; SessionFlags_Values sessionFlag = SessionFlags_Values.NONE; SigningFlagType responseSigningFlagType = SigningFlagType.SignedFlagNotSet; Packet_Header_Flags_Values headerFlags = (signingFlagType == SigningFlagType.SignedFlagSet) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE; uint status = testClient.SessionSetup( headerFlags, testConfig.DefaultSecurityPackage, testConfig.SutComputerName, GetAccountCredential(userType), true, GetSessionSetupSecurityMode(signingEnabledType, signingRequiredType), checker: (header, response) => { modelSessionId = GetModelSessionId(header.SessionId); responseSigningFlagType = GetSigningFlagType(header.Flags); sessionFlag = response.SessionFlags; }); SessionSetupResponse((ModelSmb2Status)status, modelSessionId, responseSigningFlagType, sessionFlag, signingConfig); }
private void InternalConnectShare(string domain, string userName, string password, string shareName, TimeSpan timeout, SecurityPackageType securityPackage, bool useServerToken) { uint status; DialectRevision selectedDialect; Packet_Header header; byte[] serverGssToken; Array allDialects = Enum.GetValues(typeof(DialectRevision)); DialectRevision[] validDialects = new DialectRevision[allDialects.Length - 2]; int index = 0; foreach (var dialect in allDialects) { if ((DialectRevision)dialect != DialectRevision.Smb2Unknown && (DialectRevision)dialect != DialectRevision.Smb2Wildcard) { validDialects[index++] = (DialectRevision)dialect; } } PreauthIntegrityHashID[] preauthIntegrityHashIDArray = null; EncryptionAlgorithm[] encryptionAlgorithmArray = null; if (validDialects.Contains(DialectRevision.Smb311)) { preauthIntegrityHashIDArray = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 }; encryptionAlgorithmArray = new EncryptionAlgorithm[] { EncryptionAlgorithm.ENCRYPTION_AES128_GCM, EncryptionAlgorithm.ENCRYPTION_AES128_CCM }; } // Negotiate: NEGOTIATE_Response negotiateResponse; CheckStatusCode( client.Negotiate( 1, 1, Packet_Header_Flags_Values.NONE, messageId++, // Will negotiate highest dialect server supports validDialects, SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_ENCRYPTION | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_LARGE_MTU, clientGuid, out selectedDialect, out serverGssToken, out header, out negotiateResponse, preauthHashAlgs: preauthIntegrityHashIDArray, encryptionAlgs: encryptionAlgorithmArray)); negotiatedDialect = selectedDialect; serverCapabilities = (Capabilities_Values)negotiateResponse.Capabilities; // 3.2.5.2: If the SecurityMode field in the SMB2 header of the response has the SMB2_NEGOTIATE_SIGNING_REQUIRED bit set, // the client MUST set Connection.RequireSigning to TRUE. // 3.2.5.3.1: If the global setting RequireMessageSigning is set to TRUE or // Connection.RequireSigning is set to TRUE then Session.SigningRequired MUST be set to TRUE bool session_SigningRequired = negotiateResponse.SecurityMode.HasFlag(NEGOTIATE_Response_SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED); if (session_SigningRequired) { // 3.2.4.1.1: If the client signs the request, it MUST set the SMB2_FLAGS_SIGNED bit in the Flags field of the SMB2 header. headerFlags |= Packet_Header_Flags_Values.FLAGS_SIGNED; } // Session setup: SESSION_SETUP_Response sessionSetupResponse; SspiClientSecurityContext sspiClientGss = new SspiClientSecurityContext( securityPackage, new AccountCredential(domain, userName, password), Smb2Utility.GetCifsServicePrincipalName(serverPrincipleName), ClientSecurityContextAttribute.None, SecurityTargetDataRepresentation.SecurityNativeDrep); if (securityPackage == SecurityPackageType.Negotiate) sspiClientGss.Initialize(serverGssToken); else sspiClientGss.Initialize(null); do { status = client.SessionSetup( 1, 1, Packet_Header_Flags_Values.NONE, messageId++, sessionId, SESSION_SETUP_Request_Flags.NONE, SESSION_SETUP_Request_SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, SESSION_SETUP_Request_Capabilities_Values.GLOBAL_CAP_DFS, 0, sspiClientGss.Token, out sessionId, out serverGssToken, out header, out sessionSetupResponse); CheckStatusCode(status); if ((status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED || status == Smb2Status.STATUS_SUCCESS) && serverGssToken != null && serverGssToken.Length > 0) { sspiClientGss.Initialize(serverGssToken); } } while (status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED); // 3.2.4.1.1 If Connection.Dialect is "3.1.1" and the message being sent is a TREE_CONNECT Request and the session identified by SessionId has Session.EncryptData equal to FALSE bool treeconnect_SigningRequired = session_SigningRequired || (selectedDialect >= DialectRevision.Smb311); client.GenerateCryptoKeys(sessionId, sspiClientGss.SessionKey, treeconnect_SigningRequired, false); this.sessionId = header.SessionId; // Session Key will be used in the MS-LSA SDK, see LsaClient.cs Line 179 SessionKey // Insert the session key to the global context Smb2ClientSession smb2CliSession = new Smb2ClientSession(); smb2CliSession.SessionKey = client.GetSessionKeyForAuthenticatedContext(sessionId); Smb2ClientConnection smb2CliConn = new Smb2ClientConnection(); smb2CliConn.SessionTable = new Dictionary<ulong, Smb2ClientSession>(); smb2CliConn.SessionTable.Add(sessionId, smb2CliSession); context.ConnectionTable = new Dictionary<string, Smb2ClientConnection>(); context.ConnectionTable.Add("Smb2ClientConnection", smb2CliConn); // Tree connect: TREE_CONNECT_Response treeConnectResponse; status = client.TreeConnect( 1, 1, treeconnect_SigningRequired? headerFlags| Packet_Header_Flags_Values.FLAGS_SIGNED:headerFlags, messageId++, sessionId, "\\\\" + serverPrincipleName + "\\" + shareName, out treeId, out header, out treeConnectResponse); this.treeId = header.TreeId; // For the messages followed by TREE_CONNECT, set them as signed/not signed following the normal proces client.EnableSessionSigningAndEncryption(sessionId, session_SigningRequired, false); }
protected virtual uint TreeConnect( ushort creditCharge, ushort creditRequest, Packet_Header_Flags_Values flags, ulong messageId, ulong sessionId, string server, string share, out Packet_Header header, out TREE_CONNECT_Response response) { return client.TreeConnect( creditCharge, creditRequest, flags, messageId, sessionId, string.Format(@"\\{0}\{1}", server, share), out treeId, out header, out response); }
protected override uint TreeConnect(ushort creditCharge, ushort creditRequest, Packet_Header_Flags_Values flags, ulong messageId, ulong sessionId, string server, string share, out Packet_Header header, out TREE_CONNECT_Response response) { uint treeConnectResponseCode = base.TreeConnect(creditCharge, creditRequest, flags, messageId, sessionId, server, share, out header, out response); if (supportV1) { testSite.Assert.IsTrue( response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_ENABLE_HASH_V1), "The share content should enable hash v1"); } if (supportV2) { testSite.Assert.IsTrue( response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_ENABLE_HASH_V2), "The share content should enable hash v2"); } return treeConnectResponseCode; }
private uint ReadHash( Smb2Client client, Packet_Header_Flags_Values headerFlags, ulong messageId, uint treeId, ulong sessionId, FILEID fileId, SRV_READ_HASH_Request_HashType_Values hashType, SRV_READ_HASH_Request_HashVersion_Values hashVersion, SRV_READ_HASH_Request_HashRetrievalType_Values hashRetrievalType, ulong offset, uint length, out HASH_HEADER hashHeader, out byte[] hashData) { hashHeader = new HASH_HEADER(); hashData = null; SRV_READ_HASH_Request readHashRequest = new SRV_READ_HASH_Request(); readHashRequest.HashType = hashType; readHashRequest.HashVersion = hashVersion; readHashRequest.HashRetrievalType = hashRetrievalType; readHashRequest.Offset = offset; readHashRequest.Length = length; byte[] requestInput = TypeMarshal.ToBytes(readHashRequest); byte[] responseOutput; uint status; SendIoctlPayload(client, CtlCode_Values.FSCTL_SRV_READ_HASH, requestInput, Packet_Header_Flags_Values.FLAGS_SIGNED, messageId, treeId, sessionId, fileId); ExpectIoctlPayload(client, out status, out responseOutput); if (status != Smb2Status.STATUS_SUCCESS) { return(status); } byte[] hashHeaderDataBuffer = null; switch (hashRetrievalType) { case SRV_READ_HASH_Request_HashRetrievalType_Values.SRV_HASH_RETRIEVE_HASH_BASED: hashHeaderDataBuffer = TypeMarshal.ToStruct <SRV_HASH_RETRIEVE_HASH_BASED>(responseOutput).Buffer; break; case SRV_READ_HASH_Request_HashRetrievalType_Values.SRV_HASH_RETRIEVE_FILE_BASED: hashHeaderDataBuffer = TypeMarshal.ToStruct <SRV_HASH_RETRIEVE_FILE_BASED>(responseOutput).Buffer; break; default: throw new NotImplementedException(hashRetrievalType.ToString()); } int hashHeaderLength = 0; hashHeader = TypeMarshal.ToStruct <HASH_HEADER>(hashHeaderDataBuffer, ref hashHeaderLength); hashData = hashHeaderDataBuffer.Skip(hashHeaderLength).ToArray(); return(status); }
protected override uint TreeConnect(ushort creditCharge, ushort creditRequest, Packet_Header_Flags_Values flags, ulong messageId, ulong sessionId, string server, string share, out Packet_Header header, out TREE_CONNECT_Response response) { uint treeConnectResponseCode = base.TreeConnect(creditCharge, creditRequest, flags, messageId, sessionId, server, share, out header, out response); if (supportV1) { testSite.Assert.IsTrue( response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_ENABLE_HASH_V1), "The share content should enable hash v1"); } if (supportV2) { testSite.Assert.IsTrue( response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_ENABLE_HASH_V2), "The share content should enable hash v2"); } return(treeConnectResponseCode); }
/// <summary> /// Connect to the Server and establish the named pipe transport. /// </summary> private void ConnectToServer() { smb2Client = new Smb2Client(smb2ClientTimeout); if (IPAddress.TryParse(serverName, out var serverIp)) { smb2Client.ConnectOverTCP(serverIp); } else { var serverHostEntry = Dns.GetHostEntry(serverName); smb2Client.ConnectOverTCP(serverHostEntry.AddressList[0]); } var validDialects = new DialectRevision[] { DialectRevision.Smb2002, DialectRevision.Smb21, DialectRevision.Smb30, DialectRevision.Smb302, DialectRevision.Smb311 }; var preauthIntegrityHashIDs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 }; var encryptionAlgorithms = new EncryptionAlgorithm[] { EncryptionAlgorithm.ENCRYPTION_AES128_GCM, EncryptionAlgorithm.ENCRYPTION_AES128_CCM }; var status = smb2Client.Negotiate( creditCharge: 1, creditRequest: 1, flags: defaultFlags, messageId: messageId++, // Will negotiate highest dialect server supports dialects: validDialects, securityMode: SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, capabilities: Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_ENCRYPTION | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_LARGE_MTU, clientGuid: Guid.NewGuid(), out var selectedDialect, out var serverGssToken, out Packet_Header _, out var negotiateResponse, preauthHashAlgs: preauthIntegrityHashIDs, encryptionAlgs: encryptionAlgorithms); CheckStatusCode(status, nameof(Smb2Client.Negotiate)); var sessionSiginingRequired = negotiateResponse.SecurityMode.HasFlag(NEGOTIATE_Response_SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED); if (sessionSiginingRequired) { defaultFlags |= Packet_Header_Flags_Values.FLAGS_SIGNED; } var usedSecurityPackageType = (SecurityPackageType)Enum.Parse(typeof(SecurityPackageType), securityPackage); var sspiClientGss = new SspiClientSecurityContext( usedSecurityPackageType, new AccountCredential(domainName, userName, password), Smb2Utility.GetCifsServicePrincipalName(serverName), ClientSecurityContextAttribute.None, SecurityTargetDataRepresentation.SecurityNativeDrep); if (usedSecurityPackageType == SecurityPackageType.Negotiate && useServerGssToken) { sspiClientGss.Initialize(serverGssToken); } else { sspiClientGss.Initialize(null); } do { status = smb2Client.SessionSetup( creditCharge: 1, creditRequest: 1, flags: Packet_Header_Flags_Values.NONE, messageId: messageId++, sessionId: sessionId, sessionSetupFlags: SESSION_SETUP_Request_Flags.NONE, securityMode: SESSION_SETUP_Request_SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, capabilities: SESSION_SETUP_Request_Capabilities_Values.GLOBAL_CAP_DFS, previousSessionId: 0, clientGssToken: sspiClientGss.Token, out sessionId, out serverGssToken, out _, out _); CheckStatusCode(status, nameof(Smb2Client.SessionSetup)); if ((status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED || status == Smb2Status.STATUS_SUCCESS) && serverGssToken != null && serverGssToken.Length > 0) { sspiClientGss.Initialize(serverGssToken); } } while (status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED); var treeConnectSigningRequired = sessionSiginingRequired || (selectedDialect >= DialectRevision.Smb311); smb2Client.GenerateCryptoKeys( sessionId, sspiClientGss.SessionKey, treeConnectSigningRequired, false); status = smb2Client.TreeConnect( creditCharge: 1, creditRequest: 1, flags: treeConnectSigningRequired ? defaultFlags | Packet_Header_Flags_Values.FLAGS_SIGNED : defaultFlags, messageId: messageId++, sessionId: sessionId, $"\\\\{serverName}\\IPC$", out treeId, out _, out _); CheckStatusCode(status, nameof(Smb2Client.TreeConnect)); smb2Client.EnableSessionSigningAndEncryption(sessionId, sessionSiginingRequired, false); status = smb2Client.Create( creditCharge: 1, creditRequest: 1, flags: defaultFlags, messageId: messageId++, sessionId: sessionId, treeId: treeId, path: pipeName, desiredAccess: AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE, shareAccess: ShareAccess_Values.FILE_SHARE_READ, createOptions: CreateOptions_Values.NONE, createDispositions: CreateDisposition_Values.FILE_OPEN_IF, fileAttributes: File_Attributes.NONE, impersonationLevel: ImpersonationLevel_Values.Impersonation, securityFlag: SecurityFlags_Values.NONE, requestedOplockLevel: RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, createContexts: null, out fileId, out _, out _, out _); CheckStatusCode(status, nameof(Smb2Client.Create)); }
/// <summary> /// Initialize all fields to the default values. /// </summary> private void Initialize() { Flags = testConfig.SendSignedRequest ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE; Dialect = DialectRevision.Smb2Unknown; MessageId = 0; GrantedCredit = 0; SessionKey = null; ServerGssToken = null; unchecked { TreeId = (uint)-1; } SessionId = 0; ParentDirectory = null; File = null; FileId = FILEID.Zero; IsDirectory = false; Locks = null; LockSequence = 0; LeaseState = LeaseStateValues.SMB2_LEASE_NONE; CreateContexts = null; OperationMessageId = 0; Client = new Smb2Client(Timeout); Client.DisableVerifySignature = this.testConfig.DisableVerifySignature; }
public void CreateRequest( CreateFileNameType fileNameType, CreateOptionsFileOpenReparsePointType fileOpenReparsePointType, CreateOptionsFileDeleteOnCloseType fileDeleteOnCloseType, CreateContextType contextType, ImpersonationLevelType impersonationType, CreateFileType fileType) { #region Header Packet_Header_Flags_Values headerFlag = testConfig.SendSignedRequest ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE; #endregion #region File Name string fileName = GetFileName(fileNameType); #endregion #region CreateOptions CreateOptions_Values createOptions = fileType == CreateFileType.DirectoryFile ? CreateOptions_Values.FILE_DIRECTORY_FILE : CreateOptions_Values.FILE_NON_DIRECTORY_FILE; if (fileOpenReparsePointType == CreateOptionsFileOpenReparsePointType.FileOpenReparsePointSet) { createOptions |= CreateOptions_Values.FILE_OPEN_REPARSE_POINT; } if (fileDeleteOnCloseType == CreateOptionsFileDeleteOnCloseType.FileDeteteOnCloseSet) { createOptions |= CreateOptions_Values.FILE_DELETE_ON_CLOSE; } #endregion #region CreateContexts Smb2CreateContextRequest[] createContexts = new Smb2CreateContextRequest[] { }; Create_ContextType = contextType; switch (contextType) { case CreateContextType.NoCreateContext: break; case CreateContextType.InvalidCreateContext: case CreateContextType.InvalidCreateContextSize: testClient.BeforeSendingPacket(ReplacePacketByInvalidCreateContext); break; case CreateContextType.ValidCreateContext: testConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_QUERY_ON_DISK_ID); createContexts = createContexts.Append(new Smb2CreateQueryOnDiskId()); break; default: throw new ArgumentException("contextType"); } #endregion #region ImpersonationLevel ImpersonationLevel_Values impersonation = ImpersonationLevel_Values.Impersonation; if (impersonationType == ImpersonationLevelType.InvalidImpersonationLevel) { impersonation = (ImpersonationLevel_Values)0x00000004; //Non-existed impersonation level } #endregion #region DesiredAccess AccessMask accessMask = AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE; #endregion Smb2CreateContextResponse[] contextResponse; uint status = testClient.Create( treeId, fileName, createOptions, headerFlag, out fileID, out contextResponse, createContexts: createContexts, accessMask: accessMask, checker: (header, response) => { }, impersonationLevel: impersonation); CreateResponse((ModelSmb2Status)status, createCloseConfig); }
protected override uint TreeConnect(ushort creditCharge, ushort creditRequest, Packet_Header_Flags_Values flags, ulong messageId, ulong sessionId, string server, string share, out Packet_Header header, out TREE_CONNECT_Response response) { uint treeConnectResponseCode = base.TreeConnect( creditCharge, creditRequest, flags, messageId, sessionId, server, share, out header, out response); this.isShareHashEnabled = response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_ENABLE_HASH_V1) || response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_ENABLE_HASH_V2); BaseTestSite.Assert.AreEqual( true, this.isShareHashEnabled, "The share folder should enable hash V1 or hash V2"); return treeConnectResponseCode; }
protected override uint TreeConnect(ushort creditCharge, ushort creditRequest, Packet_Header_Flags_Values flags, ulong messageId, ulong sessionId, string server, string share, out Packet_Header header, out TREE_CONNECT_Response response) { uint treeConnectResponseCode = base.TreeConnect( creditCharge, creditRequest, flags, messageId, sessionId, server, share, out header, out response); this.isShareHashEnabled = response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_ENABLE_HASH_V1) || response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_ENABLE_HASH_V2); BaseTestSite.Assert.AreEqual( true, this.isShareHashEnabled, "The share folder should enable hash V1 or hash V2"); return(treeConnectResponseCode); }
public void OpenFile( string server, string share, string file, SecurityPackageType securityPackageType, string domainName, string userName, string password, AccessMask accessMask) { IPHostEntry hostEntry = Dns.GetHostEntry(server); client.ConnectOverTCP(hostEntry.AddressList[0]); serverPrincipleName = Smb2Utility.GetPrincipleName(hostEntry.HostName); Packet_Header header; NEGOTIATE_Response negotiateResponse; DialectRevision selectedDialect; byte[] serverGssToken; CheckStatusCode( Negotiate( 1, 1, messageId++, clientGuid, out selectedDialect, out serverGssToken, out header, out negotiateResponse)); // 3.2.5.2: If the SecurityMode field in the SMB2 header of the response has the SMB2_NEGOTIATE_SIGNING_REQUIRED bit set, // the client MUST set Connection.RequireSigning to TRUE. // 3.2.5.3.1: If the global setting RequireMessageSigning is set to TRUE or // Connection.RequireSigning is set to TRUE then Session.SigningRequired MUST be set to TRUE bool session_SigningRequired = negotiateResponse.SecurityMode.HasFlag(NEGOTIATE_Response_SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED); if (session_SigningRequired) { // 3.2.4.1.1: If the client signs the request, it MUST set the SMB2_FLAGS_SIGNED bit in the Flags field of the SMB2 header. headerFlags |= Packet_Header_Flags_Values.FLAGS_SIGNED; } SESSION_SETUP_Response sessionSetupResponse; SspiClientSecurityContext sspiClientGss = new SspiClientSecurityContext( securityPackageType, new AccountCredential(domainName, userName, password), Smb2Utility.GetCifsServicePrincipalName(server), ClientSecurityContextAttribute.None, SecurityTargetDataRepresentation.SecurityNativeDrep); if (securityPackageType == SecurityPackageType.Negotiate) sspiClientGss.Initialize(serverGssToken); else sspiClientGss.Initialize(null); uint status; do { status = client.SessionSetup( 1, 1, Packet_Header_Flags_Values.NONE, messageId++, sessionId, SESSION_SETUP_Request_Flags.NONE, SESSION_SETUP_Request_SecurityMode_Values.NONE, SESSION_SETUP_Request_Capabilities_Values.NONE, 0, sspiClientGss.Token, out sessionId, out serverGssToken, out header, out sessionSetupResponse); CheckStatusCode(status); if ((status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED || status == Smb2Status.STATUS_SUCCESS) && serverGssToken != null && serverGssToken.Length > 0) { sspiClientGss.Initialize(serverGssToken); } } while (status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED); client.GenerateCryptoKeys(sessionId, sspiClientGss.SessionKey, session_SigningRequired, false); TREE_CONNECT_Response treeConnectResponse; CheckStatusCode( TreeConnect( 1, 1, headerFlags, messageId++, sessionId, server, share, out header, out treeConnectResponse)); CREATE_Response createResponse; Smb2CreateContextResponse[] serverCreateContexts; CheckStatusCode( client.Create( 1, 1, headerFlags, messageId++, sessionId, treeId, file, accessMask, ShareAccess_Values.FILE_SHARE_READ, CreateOptions_Values.NONE, CreateDisposition_Values.FILE_OPEN_IF, File_Attributes.NONE, ImpersonationLevel_Values.Impersonation, SecurityFlags_Values.NONE, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, null, out fileId, out serverCreateContexts, out header, out createResponse)); }
private SigningFlagType GetSigningFlagType(Packet_Header_Flags_Values flags) { SigningFlagType signingFlag; if (flags.HasFlag(Packet_Header_Flags_Values.FLAGS_SIGNED)) { signingFlag = SigningFlagType.SignedFlagSet; } else { signingFlag = SigningFlagType.SignedFlagNotSet; } return signingFlag; }
/// <summary> /// This method will send ComNegotiate request before sending a Negotiate request to simulate windows client behaviour. /// If ComNegotiate failed, the Negotiate request will still be sent. /// </summary> public uint MultiProtocolNegotiate( Smb2Client client, ushort creditCharge, ushort creditRequest, Packet_Header_Flags_Values flags, ulong messageId, DialectRevision[] dialects, SecurityMode_Values securityMode, Capabilities_Values capabilities, Guid clientGuid, out DialectRevision selectedDialect, out byte[] gssToken, out Packet_Header responseHeader, out NEGOTIATE_Response responsePayload) { uint status = client.MultiProtocolNegotiate( new string[] { "SMB 2.002", "SMB 2.???" }, out selectedDialect, out gssToken, out responseHeader, out responsePayload); if (responseHeader.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("ComNegotiate", responseHeader.Status); } // If server only supports Smb2002, no further SMB2 negotiate needed if (selectedDialect == DialectRevision.Smb2002) { return status; } PreauthIntegrityHashID[] preauthHashAlgs = null; EncryptionAlgorithm[] encryptionAlgs = null; // For back compatibility, if dialects contains SMB 3.11, preauthentication integrity context should be present. if (Array.IndexOf(dialects, DialectRevision.Smb311) >= 0) { preauthHashAlgs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 }; encryptionAlgs = new EncryptionAlgorithm[] { EncryptionAlgorithm.ENCRYPTION_AES128_GCM, EncryptionAlgorithm.ENCRYPTION_AES128_CCM }; } status = client.Negotiate( creditCharge, creditRequest, flags, messageId, dialects, securityMode, capabilities, clientGuid, out selectedDialect, out gssToken, out responseHeader, out responsePayload, 0, preauthHashAlgs, encryptionAlgs); return status; }
/// <summary> /// Terminate the named pipe transport. /// </summary> public void Disconnect() { if (smb2Client == null || !smb2Client.IsConnected) { return; } if (fileId.Persistent != 0 || fileId.Volatile != 0) { var status = smb2Client.Close( creditCharge: 1, creditRequest: 1, flags: defaultFlags, messageId: messageId++, sessionId: sessionId, treeId: treeId, fileId: fileId, closeFlags: Flags_Values.NONE, out _, out _); CheckStatusCode(status, nameof(Smb2Client.Close)); fileId = default(FILEID); } if (treeId != 0) { var status = smb2Client.TreeDisconnect( creditCharge: 1, creditRequest: 1, flags: defaultFlags, messageId: messageId++, sessionId: sessionId, treeId: treeId, out _, out _); CheckStatusCode(status, nameof(Smb2Client.TreeDisconnect)); treeId = 0; } if (sessionId != 0) { var status = smb2Client.LogOff( creditCharge: 1, creditRequest: 1, flags: defaultFlags, messageId: messageId++, sessionId: sessionId, out _, out _); CheckStatusCode(status, nameof(Smb2Client.LogOff)); sessionId = 0; } defaultFlags = Packet_Header_Flags_Values.NONE; messageId = 0; smb2Client.Disconnect(); smb2Client = null; }