public static SMB2Body CreateSMB2Body(byte[] vs, int offset, ESMB2Command eSMB2Command, SMB2HeaderFlags smb2HeaderFlags, NTStateType ntState) { SMB2Body sMB2Body = null; if (smb2HeaderFlags.HasFlag(SMB2HeaderFlags.ServerToRedir)) { if (ntState == NTStateType.Success || ntState == NTStateType.MoreProcessingRequired || ntState == NTStateType.LogonFailure) { switch (eSMB2Command) { case ESMB2Command.NEGOTIATE: sMB2Body = NegotiateResponse.Parser(vs, offset); break; case ESMB2Command.SESSION_SETUP: sMB2Body = SessionSetupResponse.Parser(vs, offset); break; case ESMB2Command.TREE_CONNECT: sMB2Body = TreeConnectResponse.Parser(vs, offset); break; case ESMB2Command.LOGOFF: case ESMB2Command.TREE_DISCONNECT: sMB2Body = LogoffAndTreeDisconnect.Parser(vs, offset); break; case ESMB2Command.CREATE: sMB2Body = CreateResponse.Parser(vs, offset); break; case ESMB2Command.CLOSE: sMB2Body = CloseResponse.Parser(vs, offset); break; case ESMB2Command.WRITE: sMB2Body = WriteResponse.Parser(vs, offset); break; case ESMB2Command.READ: sMB2Body = ReadResponse.Parser(vs, offset); break; case ESMB2Command.IOCTL: sMB2Body = IOCTLResponse.Parser(vs, offset); break; default: throw new Exception("UnKnow SMB2 Command"); } } else { sMB2Body = ErrorResponse.Parser(vs, offset); } } else { throw new NotImplementedException(); } return(sMB2Body); }
internal static SMB2Command GetSessionSetupResponse(SessionSetupRequest request, GSSProvider securityProvider, SMB2ConnectionState state) { // [MS-SMB2] Windows [..] will also accept raw Kerberos messages and implicit NTLM messages as part of GSS authentication. SessionSetupResponse response = new SessionSetupResponse(); byte[] outputToken; NTStatus status = securityProvider.AcceptSecurityContext(ref state.AuthenticationContext, request.SecurityBuffer, out outputToken); if (status != NTStatus.STATUS_SUCCESS && status != NTStatus.SEC_I_CONTINUE_NEEDED) { string userName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.UserName) as string; string domainName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.DomainName) as string; string machineName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.MachineName) as string; string osVersion = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.OSVersion) as string; state.LogToServer(Severity.Information, "Session Setup: User '{0}' failed authentication (Domain: '{1}', Workstation: '{2}', OS version: '{3}'), NTStatus: {4}", userName, domainName, machineName, osVersion, status); return(new ErrorResponse(request.CommandName, status)); } if (outputToken != null) { response.SecurityBuffer = outputToken; } // According to [MS-SMB2] 3.3.5.5.3, response.Header.SessionID must be allocated if the server returns STATUS_MORE_PROCESSING_REQUIRED if (request.Header.SessionID == 0) { ulong?sessionID = state.AllocateSessionID(); if (!sessionID.HasValue) { return(new ErrorResponse(request.CommandName, NTStatus.STATUS_TOO_MANY_SESSIONS)); } response.Header.SessionID = sessionID.Value; } if (status == NTStatus.SEC_I_CONTINUE_NEEDED) { response.Header.Status = NTStatus.STATUS_MORE_PROCESSING_REQUIRED; } else // status == STATUS_SUCCESS { string userName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.UserName) as string; string domainName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.DomainName) as string; string machineName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.MachineName) as string; string osVersion = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.OSVersion) as string; byte[] sessionKey = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.SessionKey) as byte[]; object accessToken = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.AccessToken); bool? isGuest = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.IsGuest) as bool?; if (!isGuest.HasValue || !isGuest.Value) { state.LogToServer(Severity.Information, "Session Setup: User '{0}' authenticated successfully (Domain: '{1}', Workstation: '{2}', OS version: '{3}').", userName, domainName, machineName, osVersion); bool signingRequired = (request.SecurityMode & SecurityMode.SigningRequired) > 0; SMB2Dialect smb2Dialect = SMBServer.ToSMB2Dialect(state.Dialect); byte[] signingKey = SMB2Cryptography.GenerateSigningKey(sessionKey, smb2Dialect, null); state.CreateSession(request.Header.SessionID, userName, machineName, sessionKey, accessToken, signingRequired, signingKey); } else { state.LogToServer(Severity.Information, "Session Setup: User '{0}' failed authentication (Domain: '{1}', Workstation: '{2}', OS version: '{3}'), logged in as guest.", userName, domainName, machineName, osVersion); state.CreateSession(request.Header.SessionID, "Guest", machineName, sessionKey, accessToken, false, null); response.SessionFlags = SessionFlags.IsGuest; } } return(response); }