/// <summary> /// remove the session. if session does not exists, do nothing. /// </summary> /// <param name="session">the session to remove</param> internal void RemoveSession(SmbServerSession session) { lock (this.sessionTable) { if (this.sessionTable.Contains(session)) { this.sessionTable.Remove(session); } } }
/// <summary> /// add a session to the session table of connection /// </summary> /// <param name="session">the session to add</param> /// <exception cref="InvalidOperationException"> /// the session has exist in the connection, can not add it! /// </exception> internal void AddSession(SmbServerSession session) { lock (this.sessionTable) { if (this.sessionTable.Contains(session)) { throw new InvalidOperationException("the session has exist in the connection, can not add it!"); } this.sessionTable.Add(session); } }
/// <summary> /// update the context with response packet /// </summary> /// <param name="connection">the connection of endpoint</param> /// <param name="packet">the packet to update the context</param> private void ResponsePacketUpdateRoleContext(SmbServerConnection connection, SmbPacket packet) { SmbHeader smbHeader = packet.SmbHeader; SmbPacket requestPacket = connection.GetRequestPacket(smbHeader.Mid); if (requestPacket == null) { return; } switch (smbHeader.Command) { case SmbCommand.SMB_COM_SESSION_SETUP_ANDX: if (smbHeader.Uid == 0) { break; } else { SmbServerSession session = new SmbServerSession(); session.Uid = smbHeader.Uid; session.AuthenticationState = SessionState.Complete; session.Connection = connection; session.SessionKey = connection.GssApi.SessionKey; connection.AddSession(session); } break; case SmbCommand.SMB_COM_LOGOFF_ANDX: if (requestPacket.SmbHeader.Uid == 0) { break; } else { connection.RemoveSession(connection.GetSession(requestPacket.SmbHeader.Uid)); } break; case SmbCommand.SMB_COM_TREE_CONNECT_ANDX: { SmbTreeConnectAndxRequestPacket request = requestPacket as SmbTreeConnectAndxRequestPacket; SmbServerTreeConnect treeconnect = new SmbServerTreeConnect(); treeconnect.TreeId = smbHeader.Tid; treeconnect.Session = connection.GetSession(smbHeader.Uid); if (treeconnect.Session == null) { break; } if ((request.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE) != 0) { treeconnect.Path = Encoding.Unicode.GetString(request.SmbData.Path); } else { treeconnect.Path = Encoding.ASCII.GetString(request.SmbData.Path); } treeconnect.Path = treeconnect.Path.TrimEnd('\0'); treeconnect.Session.AddTreeConnect(treeconnect); } break; case SmbCommand.SMB_COM_TREE_DISCONNECT: if (requestPacket.SmbHeader.Uid != 0) { SmbServerSession session = connection.GetSession(requestPacket.SmbHeader.Uid); if (session == null) { break; } session.RemoveTreeConnect(session.GetTreeConnect(requestPacket.SmbHeader.Tid)); } break; case SmbCommand.SMB_COM_NT_CREATE_ANDX: { SmbNtCreateAndxResponsePacket response = packet as SmbNtCreateAndxResponsePacket; SmbNtCreateAndxRequestPacket request = requestPacket as SmbNtCreateAndxRequestPacket; SmbServerOpen open = new SmbServerOpen(); open.SmbFid = response.SmbParameters.FID; open.PathName = SmbMessageUtils.GetString(request.SmbData.FileName, SmbFlags2.SMB_FLAGS2_UNICODE == (request.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE)); open.PathName = open.PathName.TrimEnd('\0'); open.Session = connection.GetSession(smbHeader.Uid); open.TreeConnect = connection.GetTreeConnect(smbHeader.Tid); if (open.TreeConnect == null) { break; } open.TreeConnect.AddOpen(open); } break; case SmbCommand.SMB_COM_OPEN_ANDX: { SmbOpenAndxResponsePacket response = packet as SmbOpenAndxResponsePacket; SmbOpenAndxRequestPacket request = requestPacket as SmbOpenAndxRequestPacket; SmbServerOpen open = new SmbServerOpen(); open.SmbFid = response.SmbParameters.FID; open.PathName = SmbMessageUtils.GetString(request.SmbData.FileName, SmbFlags2.SMB_FLAGS2_UNICODE == (request.SmbHeader.Flags2 & SmbFlags2.SMB_FLAGS2_UNICODE)); open.Session = connection.GetSession(smbHeader.Uid); open.TreeConnect = connection.GetTreeConnect(smbHeader.Tid); if (open.TreeConnect == null) { break; } open.TreeConnect.AddOpen(open); } break; case SmbCommand.SMB_COM_CLOSE: { SmbCloseRequestPacket closeRequest = requestPacket as SmbCloseRequestPacket; SmbServerTreeConnect treeconnect = connection.GetTreeConnect(requestPacket.SmbHeader.Tid); if (treeconnect == null) { break; } treeconnect.RemoveOpen(treeconnect.GetOpen(closeRequest.SmbParameters.FID)); } break; default: break; } connection.RemoveRequestPacket(packet); }
/// <summary> /// update the context with request packet /// </summary> /// <param name="connection">the connection of endpoint</param> /// <param name="packet">the packet to update the context</param> private void RequestPacketUpdateRoleContext(SmbServerConnection connection, SmbPacket packet) { connection.AddRequestPacket(packet); // update the message id connection.MessageId = packet.SmbHeader.Mid; // update the process id connection.ProcessId = (uint)(packet.SmbHeader.PidHigh << 16); connection.ProcessId += packet.SmbHeader.PidLow; // update the message sign sequence number if (packet.SmbHeader.SecurityFeatures != 0 && connection.GssApi != null && connection.GssApi.SessionKey != null) { if (packet.SmbHeader.Command == SmbCommand.SMB_COM_NT_CANCEL) { connection.ServerNextReceiveSequenceNumber++; } else { ServerSendSequenceNumberKey key = new ServerSendSequenceNumberKey(); key.PidHigh = packet.SmbHeader.PidHigh; key.PidLow = packet.SmbHeader.PidLow; key.Mid = packet.SmbHeader.Mid; connection.ServerSendSequenceNumber[key] = connection.ServerNextReceiveSequenceNumber + 1; connection.ServerNextReceiveSequenceNumber += 2; } } // process each special command switch (packet.SmbHeader.Command) { case SmbCommand.SMB_COM_NEGOTIATE: SmbNegotiateRequestPacket request = packet as SmbNegotiateRequestPacket; byte[] dialects = request.SmbData.Dialects; List <string> negotiateDialects = new List <string>(); for (int i = 0; i < dialects.Length; i++) { if (dialects[i] == 0x02) { continue; } string dialect = ""; for (; i < dialects.Length && dialects[i] != 0x00; i++) { dialect += (char)dialects[i]; } negotiateDialects.Add(dialect); } connection.NegotiatedDialects = negotiateDialects.ToArray(); break; case SmbCommand.SMB_COM_TREE_CONNECT_ANDX: // down-case the packet Cifs.SmbTreeConnectAndxRequestPacket treeconnect = packet as Cifs.SmbTreeConnectAndxRequestPacket; // get the specified session. SmbServerSession treeconnectSession = connection.GetSession((ushort)treeconnect.SmbHeader.Uid); if (treeconnectSession == null) { return; } // Calculate the one-way hash byte[] sessionKey = FileServiceUtils.ProtectSessionKey(treeconnectSession.SessionKey); // update the session key state. treeconnectSession.SessionKeyState = SessionKeyStateValue.Available; // if server does not support SMB_EXTENDED_SIGNATURES, return. if (SmbClientTreeConnect.TreeConnectAndxExtendedSignatures != (treeconnect.SmbParameters.Flags & SmbClientTreeConnect.TreeConnectAndxExtendedSignatures)) { return; } treeconnectSession.SessionKey = sessionKey; break; default: return; } return; }