/// <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>
 /// 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);
            }
        }
Example #6
0
        /// <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;
        }
Example #7
0
        /// <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);
        }