/// <summary>
        /// Constructor
        /// </summary>
        /// <param name="config">The config, contains information about transport type, tcp listening port and so on</param>
        public Smb2Server(Smb2ServerConfig config)
        {
            decoder = new Smb2Decoder(Smb2Role.Server);
            decoder.TransportType = config.TransportType;

            clientEndpoints = new List<Smb2Endpoint>();
            context = new Smb2ServerContext();
            context.transportType = config.TransportType;
            context.requireMessageSigning = config.RequireMessageSigning;
            context.isDfsCapable = config.IsDfsCapable;

            transportType = config.TransportType;

            if (transportType == Smb2TransportType.NetBios)
            {
                NetbiosTransportConfig netbiosConfig = new NetbiosTransportConfig();
                netbiosConfig.BufferSize = Smb2Consts.MaxNetbiosBufferSize;

                netbiosConfig.LocalNetbiosName = config.LocalNetbiosName;
                netbiosConfig.MaxNames = Smb2Consts.MaxNames;
                netbiosConfig.MaxSessions = Smb2Consts.MaxSessions;
                netbiosConfig.Type = StackTransportType.Netbios;
                netbiosConfig.Role = Role.Server;

                transport = new TransportStack(netbiosConfig, decoder.Smb2DecodePacketCallback);
            }
            else if (transportType == Smb2TransportType.Tcp)
            {
                SocketTransportConfig socketConfig = new SocketTransportConfig();

                socketConfig.BufferSize = Smb2Consts.MaxNetbiosBufferSize;
                socketConfig.MaxConnections = Smb2Consts.MaxConnectionNumer;
                socketConfig.LocalIpAddress = IPAddress.Any;
                socketConfig.LocalIpPort = config.ServerTcpListeningPort;
                socketConfig.Role = Role.Server;
                socketConfig.Type = StackTransportType.Tcp;

                transport = new TransportStack(socketConfig, decoder.Smb2DecodePacketCallback);
            }
            else
            {
                throw new ArgumentException("config contains invalid transport type", "config");
            }
        }
        /// <summary>
        /// to update the config of transport at runtime.
        /// </summary>
        /// <param name="config">
        /// a TransportConfig object that contains the config to update
        /// </param>
        /// <exception cref="ArgumentException">
        /// thrown when transportConfig is not SocketTransportConfig
        /// </exception>
        /// <exception cref="ObjectDisposedException">
        /// thrown when this object is disposed.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when config is null.
        /// </exception>
        public void UpdateConfig(TransportConfig config)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("TcpClientTransport");
            }

            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            SocketTransportConfig socketTransportConfig = config as SocketTransportConfig;

            if (socketTransportConfig == null)
            {
                throw new ArgumentException("transportConfig must be SocketTransportConfig", "config");
            }

            this.socketConfig = socketTransportConfig;
        }
Exemplo n.º 3
0
        /// <summary>
        /// get the endpoint to listen by the port.<para/>
        /// retrieve the address from socket config.
        /// </summary>
        /// <param name="socketConfig">
        /// a SocketTransportConfig object that contains the LocalAddress.
        /// </param>
        /// <param name="localEndPoint">
        /// an int value that specifies the port to start at.
        /// </param>
        /// <returns>
        /// an IPEndPoint object that specifies the endpoint to listen at.
        /// </returns>
        public static IPEndPoint GetEndPointByPort(SocketTransportConfig socketConfig, object localEndPoint)
        {
            int port;

            try
            {
                port = Convert.ToInt32(localEndPoint, CultureInfo.InvariantCulture);
            }
            catch (Exception)
            {
                throw new ArgumentException("localEndPoint is not an IPEndPoint/port.", "localEndPoint");
            }

            if (socketConfig.LocalIpAddress == null)
            {
                throw new InvalidOperationException(
                          "localEndPoint is an int port, but the LocalIpAddress is not configured.");
            }

            return(new IPEndPoint(socketConfig.LocalIpAddress, port));
        }
        public void Start(ushort localPort, KileConnectionType transportType, KileIpType ipType, int transportSize)
        {
            SocketTransportConfig transportConfig = new SocketTransportConfig();
            transportConfig.Role = Role.Server;
            transportConfig.MaxConnections = ConstValue.MAX_CONNECTIONS;
            transportConfig.BufferSize = transportSize;

            if (ipType == KileIpType.Ipv4)
            {
                transportConfig.LocalIpAddress = IPAddress.Any;
            }
            else
            {
                transportConfig.LocalIpAddress = IPAddress.IPv6Any;
            }
            transportConfig.LocalIpPort = localPort;

            if (transportType == KileConnectionType.TCP)
            {
                transportConfig.Type = StackTransportType.Tcp;
            }
            else if (transportType == KileConnectionType.UDP)
            {
                transportConfig.Type = StackTransportType.Udp;
            }
            else
            {
                throw new ArgumentException("ConnectionType can only be TCP or UDP.");
            }
            decoder = new KileDecoder(contextList, transportType);
            transport = new TransportStack(transportConfig, decoder.DecodePacketCallback);
            transport.Start();
        }
        /// <summary>
        /// to set up the tcp connection, and add the connection into context. Exception will  be thrown if failed to 
        /// set up connection with server. 
        /// </summary>
        /// <param name = "serverName">the server name or server ip address to connect to </param>
        /// <param name = "serverPort">the port of server to connect to </param>
        /// <param name = "ipVersion">the ipversion to connect to server </param>
        /// <param name = "bufferSize">the buffer size of transport </param>
        /// <exception cref="InvalidOperationException">
        /// Failed to get the IP address of SMB server in SmbClient().
        /// </exception>
        public virtual void Connect(string serverName, int serverPort, IpVersion ipVersion, int bufferSize)
        {
            // initialize the config for transport
            SocketTransportConfig config = new SocketTransportConfig();

            config.Role = Role.Client;
            config.Type = StackTransportType.Tcp;
            config.BufferSize = bufferSize;

            // init remote address of config
            #region Lookup the ip address from server name.

            IPHostEntry ipHostEntry = Dns.GetHostEntry(serverName);
            if (ipHostEntry != null)
            {
                foreach (IPAddress address in ipHostEntry.AddressList)
                {
                    if (ipVersion != IpVersion.Ipv4 && address.AddressFamily == AddressFamily.InterNetworkV6)
                    {
                        config.LocalIpAddress = IPAddress.IPv6Any;
                        config.RemoteIpAddress = address;
                        break;
                    }
                    else if (ipVersion != IpVersion.Ipv6 && address.AddressFamily == AddressFamily.InterNetwork)
                    {
                        config.LocalIpAddress = IPAddress.Any;
                        config.RemoteIpAddress = address;
                        break;
                    }
                    else
                    {
                        continue;
                    }
                }
            }
            if (config.RemoteIpAddress == null)
            {
                throw new InvalidOperationException("Failed to get the IP address of SMB server in SmbClient().");
            }

            #endregion

            // init remote port
            config.RemoteIpPort = serverPort;

            // init local address of config
            config.LocalIpAddress = IPAddress.Any;
            config.LocalIpPort = 0;

            // init transport
            this.transport = new TransportStack(config, new SmbClientDecodePacket(this).DecodePacket);

            // connect to server.
            object endPointIdentity = this.transport.Connect();

            // initialize the connection
            SmbClientConnection connection = new SmbClientConnection();

            connection.ConnectionId = this.Context.GetConnectionID(endPointIdentity as IPEndPoint);
            connection.ConnectionState = StackTransportState.ConnectionEstablished;
            connection.MaxBufferSize = (uint)bufferSize;

            // update the context
            this.cifsClient.Context.AddOrUpdateConnection(connection);

            // update the connection id, to identity the connection instance.
            this.ConnectionId = connection.ConnectionId;

            // set the transport type
            this.capability.TransportType = TransportType.TCP;
        }
        /// <summary>
        /// to start the smbserver, tcp transport.
        /// </summary>
        /// <param name="serverAddress">the address of server</param>
        /// <param name="localPort">the local port to bind for server</param>
        /// <param name="maxConnections">the max connections of server capability</param>
        /// <param name="bufferSize">the buffer size of transport </param>
        /// <param name="accountCredential">the credential to authenticate client, spn is always cifs/machine</param>
        public virtual void Start(IPAddress serverAddress, int localPort, int maxConnections, int bufferSize, AccountCredential accountCredential)
        {
            this.credential = accountCredential;

            SocketTransportConfig config = new SocketTransportConfig();

            config.Type = StackTransportType.Tcp;
            config.Role = Role.Server;
            config.LocalIpAddress = serverAddress;
            config.LocalIpPort = localPort;
            config.MaxConnections = maxConnections;
            config.BufferSize = bufferSize;

            SmbServerDecodePacket decoder = new SmbServerDecodePacket();
            decoder.Context = this.context;

            this.transport = new TransportStack(config, decoder.DecodePacket);
            this.transport.Start();

            this.transportType = TransportType.TCP;
        }
        /// <summary>
        /// to update the config of transport at runtime.
        /// </summary>
        /// <param name="config">
        /// a TransportConfig object that contains the config to update
        /// </param>
        /// <exception cref="ObjectDisposedException">
        /// thrown when this object is disposed.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// thrown when transportConfig is not SocketTransportConfig.
        /// </exception>
        public void UpdateConfig(TransportConfig config)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("TcpServerTransport");
            }

            SocketTransportConfig socketTransportConfig = config as SocketTransportConfig;

            if (socketTransportConfig == null)
            {
                throw new ArgumentException("transportConfig must be SocketTransportConfig", "config");
            }

            this.socketConfig = socketTransportConfig;
        }
        /// <summary>
        /// Starts the server to listen on specified port.
        /// </summary>
        public void Start()
        {
            if (transportStack == null)
            {
                SocketTransportConfig transportConfig = new SocketTransportConfig();
                transportConfig.LocalIpAddress = IPAddress.Any;
                transportConfig.LocalIpPort = this.listenPort;
                transportConfig.Role = Role.Server;
                transportConfig.BufferSize = DefaultBufferSize;
                transportConfig.MaxConnections = int.MaxValue;
                transportConfig.Type = isTcp ? StackTransportType.Tcp : StackTransportType.Udp;

                this.transportStack = new TransportStack(transportConfig, decoder.DecodeLdapPacketCallBack);
            }

            this.transportStack.Start();
        }
        public virtual RpceServerContext StartTcp(ushort port)
        {
            lock (this.tcpThreadLocker)
            {
                RpceServerContext serverContext = this.serverContextManager.LookupServerContext(
                    RpceUtility.RPC_OVER_TCPIP_PROTOCOL_SEQUENCE,
                    port.ToString());

                if (serverContext != null)
                {
                    throw new InvalidOperationException("The server with the port has been started. Please try other port.");
                }

                serverContext = new RpceServerContext(
                        RpceUtility.RPC_OVER_TCPIP_PROTOCOL_SEQUENCE,
                        port.ToString());

                this.serverContextManager.AddServerContext(serverContext);
                if (this.openedTcpPortList == null)
                {
                    this.openedTcpPortList = new List<ushort>();
                }
                this.openedTcpPortList.Add(port);

                bool ipv4Started = false;
                bool ipv6Started = false;
                Exception ex = null;

                try
                {
                    if (this.tcpTransport == null)
                    {
                        SocketTransportConfig config = new SocketTransportConfig();
                        config.Type = StackTransportType.Tcp;
                        config.Role = Role.Server;
                        config.LocalIpAddress = IPAddress.Any;
                        config.MaxConnections = RpceServerContext.DEFAULT_MAX_CONNECTIONS;
                        config.BufferSize = Math.Max(serverContext.MaxReceiveFragmentSize, serverContext.MaxTransmitFragmentSize);

                        this.tcpTransport = new TransportStack(config, RpceDecodePduCallback);
                    }
                }
                catch (Exception e)
                {
                    ex = e;
                    this.tcpTransport = null;
                }

                try
                {
                    //Start IPv4
                    IPEndPoint ipv4Endpoint = new IPEndPoint(IPAddress.Any, port);
                    this.tcpTransport.Start(ipv4Endpoint);
                    ipv4Started = true;
                }
                catch (Exception e)
                {
                    ex = e;
                }

                //Start IPv6
                try
                {
                    IPEndPoint ipv6Endpoint = new IPEndPoint(IPAddress.IPv6Any, port);
                    this.tcpTransport.Start(ipv6Endpoint);
                    ipv6Started = true;
                }
                catch (Exception e)
                {
                    ex = e;
                }

                if (!ipv4Started && !ipv6Started)
                {
                    this.serverContextManager.RemoveServerContext(serverContext);
                    this.openedTcpPortList.Remove(port);
                    throw new InvalidOperationException("TCP server failed to start.", ex);
                }

                if (this.tcpReceiveThread == null)
                {
                    this.tcpReceiveThread = new Thread(TcpReceiveLoop);
                    this.tcpReceiveThread.Start();
                }

                return serverContext;
            }
        }
        /// <summary>
        /// Set up the TCP/UDP transport connection with KDC.
        /// </summary>
        /// <exception cref="System.ArgumentException">Thrown when the connection type is neither TCP nor UDP</exception>
        public virtual void Connect()
        {
            SocketTransportConfig transportConfig = new SocketTransportConfig();
            transportConfig.Role = Role.Client;
            transportConfig.MaxConnections = 1;
            transportConfig.BufferSize = TransportBufferSize;
            transportConfig.RemoteIpPort = kdcPort;
            transportConfig.RemoteIpAddress = IPAddress.Parse(kdcAddress);

            // For UDP bind
            if (transportConfig.RemoteIpAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
            {
                transportConfig.LocalIpAddress = IPAddress.Any;
            }
            else if (transportConfig.RemoteIpAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
            {
                transportConfig.LocalIpAddress = IPAddress.IPv6Any;
            }

            if (transportType == TransportType.TCP)
            {
                transportConfig.Type = StackTransportType.Tcp;
            }
            else if (transportType == TransportType.UDP)
            {
                transportConfig.Type = StackTransportType.Udp;
            }
            else
            {
                throw new ArgumentException("ConnectionType can only be TCP or UDP.");
            }

            kdcTransport = new TransportStack(transportConfig, DecodePacketCallback);
            if (transportType == TransportType.TCP)
            {
                kdcTransport.Connect();
            }
            else
            {
                kdcTransport.Start();
            }
        }
        public void Connect(
            string protocolSequence,
            string networkAddress,
            string endpoint,
            AccountCredential transportCredential,
            TimeSpan timeout,
            SecurityPackageType securityPackage)
        {
            if (protocolSequence == null)
            {
                throw new ArgumentNullException("protocolSequence");
            }
            if (networkAddress == null)
            {
                throw new ArgumentNullException("networkAddress");
            }
            if (endpoint == null)
            {
                throw new ArgumentNullException("endpoint");
            }

            if (context.tcpTransport != null || context.fileServiceTransport != null)
            {
                throw new InvalidOperationException("RPCE is already connected.");
            }

            if (string.Compare(protocolSequence, RpceUtility.RPC_OVER_TCPIP_PROTOCOL_SEQUENCE, true) == 0)
            {
                IPAddress[] addresses = Dns.GetHostAddresses(networkAddress);
                if (addresses == null || addresses.Length == 0)
                {
                    throw new ArgumentException(
                        "Cannot resolve network address.",
                        "networkAddress");
                }
                IPAddress addr = addresses[0];

                int port;
                if (!int.TryParse(endpoint, out port))
                {
                    throw new ArgumentException("Invalid endpoint.", "endpoint");
                }

                SocketTransportConfig config = new SocketTransportConfig();
                config.BufferSize = Math.Max(context.MaxTransmitFragmentSize, context.MaxReceiveFragmentSize);
                config.RemoteIpAddress = addr;
                config.RemoteIpPort = port;
                config.Role = Role.Client;
                config.Type = StackTransportType.Tcp;

                context.tcpTransport = new TransportStack(config, RpceDecodePduCallback);
                context.tcpTransport.Connect();
            }
            else if (string.Compare(protocolSequence, RpceUtility.RPC_OVER_NAMED_PIPE_PROTOCOL_SEQUENCE, true) == 0)
            {
                if (!endpoint.StartsWith(
                    RpceUtility.NAMED_PIPE_ENDPOINT_PREFIX,
                    StringComparison.InvariantCultureIgnoreCase))
                {
                    throw new ArgumentException("endpoint format is incorrect.", "endpoint");
                }

                if (transportCredential == null)
                {
                    throw new ArgumentNullException("transportCredential");
                }

                timeoutForFsTransport = timeout;
                pipeTransceiveResponseQueue = new Queue<byte[]>();

                if (!RpceUtility.DisableSmb2)
                {
                    try
                    {
                        context.fileServiceTransport = new Smb2ClientTransport(timeout);
                        context.fileServiceTransport.ConnectShare(
                            networkAddress,
                            RpceUtility.NAMED_PIPE_PORT,
                            IpVersion.Any,
                            transportCredential.DomainName,
                            transportCredential.AccountName,
                            transportCredential.Password,
                            RpceUtility.NAMED_PIPE_SHARENAME,
                            securityPackage,
                            false);
                    }
                    catch
                    {
                        context.fileServiceTransport.Dispose();
                        context.fileServiceTransport = null;
                    }
                }

                if (context.fileServiceTransport == null)
                {
                    // Remote doesn't support SMB2, use SMB.
                    context.fileServiceTransport = new SmbClientTransport();
                    context.fileServiceTransport.ConnectShare(
                        networkAddress,
                        RpceUtility.NAMED_PIPE_PORT,
                        IpVersion.Any,
                        transportCredential.DomainName,
                        transportCredential.AccountName,
                        transportCredential.Password,
                        RpceUtility.NAMED_PIPE_SHARENAME,
                        securityPackage,
                        false);
                }

                context.fileServiceTransport.Create(
                    endpoint.Substring(RpceUtility.NAMED_PIPE_ENDPOINT_PREFIX.Length),
                    FsFileDesiredAccess.FILE_READ_DATA | FsFileDesiredAccess.FILE_WRITE_DATA
                    | FsFileDesiredAccess.FILE_APPEND_DATA
                    | FsFileDesiredAccess.FILE_READ_EA | FsFileDesiredAccess.FILE_WRITE_EA
                    | FsFileDesiredAccess.FILE_READ_ATTRIBUTES | FsFileDesiredAccess.FILE_WRITE_ATTRIBUTES
                    | FsFileDesiredAccess.READ_CONTROL | FsFileDesiredAccess.SYNCHRONIZE,
                    FsImpersonationLevel.Impersonation,
                    FsFileAttribute.NONE,
                    FsCreateDisposition.FILE_OPEN,
                    FsCreateOption.FILE_NON_DIRECTORY_FILE | FsCreateOption.FILE_OPEN_NO_RECALL);
            }
            else
            {
                throw new NotSupportedException("Specified protocol sequence is not supported.");
            }

            context.ProtocolSequence = protocolSequence;
            context.NetworkAddress = networkAddress;
            context.Endpoint = endpoint;

            // Make handle always different.
            handle = new IntPtr(Environment.TickCount);
        }