/// <summary>
 /// Constructor
 /// </summary>
 /// <param name="account">Client account credential.</param>
 /// <param name="target">Target name.</param>
 public NlmpClientSecurityConfig(
     AccountCredential account,
     string target)
     : base(SecurityPackageType.Ntlm)
 {
     this.clientCredential = account;
     this.targetName = target;
 }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="clientCredential">Client account credential.</param>
 /// <param name="serverPrincipal">Server principal.</param>
 /// <param name="contextAttributes">Client security context attributes.</param>
 /// <param name="targetDataRep">The data representation, such as byte ordering, on the target.</param>
 public SspiClientSecurityConfig(
     AccountCredential clientCredential,
     string serverPrincipal,
     ClientSecurityContextAttribute contextAttributes,
     SecurityTargetDataRepresentation targetDataRep)
     : base(SecurityPackageType.Unknown)
 {
     this.clientCredential = clientCredential;
     this.serverPrincipal = serverPrincipal;
     this.securityAttributes = contextAttributes;
     this.targetDataRep = targetDataRep;
 }
Exemple #3
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="clientCredential">Client account credential.</param>
 /// <param name="serverPrincipal">Server principal.</param>
 /// <param name="contextAttributes">Client security context attributes.</param>
 /// <param name="targetDataRep">The data representation, such as byte ordering, on the target.</param>
 public SspiClientSecurityConfig(
     AccountCredential clientCredential,
     string serverPrincipal,
     ClientSecurityContextAttribute contextAttributes,
     SecurityTargetDataRepresentation targetDataRep)
     : base(SecurityPackageType.Unknown)
 {
     this.clientCredential   = clientCredential;
     this.serverPrincipal    = serverPrincipal;
     this.securityAttributes = contextAttributes;
     this.targetDataRep      = targetDataRep;
 }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="flags">Negotiation flags.</param>
 /// <param name="clientCredential">Client account credential.</param>
 /// <param name="isDomainJoined">Joined in a domain or not</param>
 /// <param name="netbiosDomainName">Netbios domain name.</param>
 /// <param name="netbiosMachineName">Netbios machine name.</param>
 public NlmpServerSecurityConfig(
     NegotiateTypes flags,
     NlmpClientCredential clientCredential,
     bool isDomainJoined,
     string netbiosDomainName,
     string netbiosMachineName)
     : base(SecurityPackageType.Ntlm)
 {
     this.negotiateflags = flags;
     this.clientCredential = clientCredential;
     this.isDomainJoined = isDomainJoined;
     this.netbiosDomainName = netbiosDomainName;
     this.netbiosMachineName = netbiosMachineName;
     this.targetName = clientCredential.TargetName;
 }
        /// <summary>
        /// Set up an RPC session with a specific server.
        /// </summary>
        /// <param name="serverName">Server computer name</param>
        /// <param name="credential">User account used to setup this session</param>
        /// <param name="securityContext">Security context of session</param>
        public void Bind(
            string serverName,
            AccountCredential credential,
            ClientSecurityContext securityContext)
        {
            if (string.IsNullOrEmpty(serverName))
            {
                throw new ArgumentNullException("serverName");
            }

            InnerBind(
                RpceUtility.RPC_OVER_NAMED_PIPE_PROTOCOL_SEQUENCE,
                serverName,
                SrvsUtility.SRVS_NAMED_PIPE,
                credential,
                securityContext);
        }
        public FSDetector(Logger logger, 
            string targetSUT,
            AccountCredential accountCredential,
            SecurityPackageType securityPackageType)
        {
            SUTName = targetSUT;
            Credential = accountCredential;
            SecurityPackageType = securityPackageType;

            logWriter = logger;
            logWriter.AddLog(LogLevel.Information, string.Format("SutName: {0}", SUTName));
            logWriter.AddLog(LogLevel.Information, string.Format("DomainName: {0}", Credential.DomainName));
            logWriter.AddLog(LogLevel.Information, string.Format("UserName: {0}", Credential.AccountName));
            logWriter.AddLog(LogLevel.Information, string.Format("UserPassword: {0}", Credential.Password));
            logWriter.AddLog(LogLevel.Information, string.Format("SecurityPackageType: {0}", SecurityPackageType.ToString()));
            logWriter.AddLineToLog(LogLevel.Information);
        }
Exemple #7
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="packageType">Specifies the name of the security package with which these credentials will be used
 /// </param>
 /// <param name="serverCredential">The credential of server, if null, use default user account.</param>
 /// <param name="serverPrincipal">Server principal name</param>
 /// <param name="contextAttributes">Bit flags that specify the attributes required by the server to establish
 /// the context</param>
 /// <param name="targetDataRep">The data representation, such as byte ordering, on the target. This parameter
 /// can be either SECURITY_NATIVE_DREP or SECURITY_NETWORK_DREP.</param>
 public SspiServerSecurityContext(
     SecurityPackageType packageType,
     AccountCredential serverCredential,
     string serverPrincipal,
     ServerSecurityContextAttribute contextAttributes,
     SecurityTargetDataRepresentation targetDataRep)
 {
     this.packageType               = packageType;
     this.serverPrincipalName       = serverPrincipal;
     this.securityContextAttributes = contextAttributes;
     this.targetDataRepresentaion   = targetDataRep;
     SspiUtility.AcquireCredentialsHandle(
         packageType,
         serverCredential,
         serverPrincipal,
         NativeMethods.SECPKG_CRED_INBOUND,
         out this.credentialHandle);
 }
        /// <summary>
        /// Initialize RpceServerContext.
        /// </summary>
        /// <param name="protocolSequence">The RPC protocol sequence strings.</param>
        /// <param name="endpoint">The endpoint of server.</param>
        /// <param name="namedPipeTransportCredential">Credential for namepiped transport.</param>
        internal RpceServerContext(
            String protocolSequence,
            String endpoint,
            AccountCredential namedPipeTransportCredential)
        {
            this.protocolSequence = protocolSequence;
            this.endpoint = endpoint;
            this.namedPipeTransportCredential = namedPipeTransportCredential;

            this.sessions = new Dictionary<string, RpceServerSessionContext>();
            this.tempSessions = new Dictionary<string, RpceServerSessionContext>();

            //set default value
            this.maxReceiveFragmentSize = RpceUtility.DEFAULT_MAX_RECEIVE_FRAGMENT_SIZE;
            this.maxTransmitFragmentSize = RpceUtility.DEFAULT_MAX_TRANSMIT_FRAGMENT_SIZE;
            this.rpcVersionMajor = 5;
            this.rpcVersionMinor = 1;
            this.ndrVersion = RpceNdrVersion.NDR;
        }
Exemple #9
0
        /// <summary>
        /// Constructor. Convert account
        /// </summary>
        /// <param name="credential">Account credential</param>
        public SecurityWinntAuthIdentity(AccountCredential credential)
        {
            this.User           = IntPtr.Zero;
            this.UserLength     = 0;
            this.Domain         = IntPtr.Zero;
            this.DomainLength   = 0;
            this.Password       = IntPtr.Zero;
            this.PasswordLength = 0;
            this.Flags          = NativeMethods.SEC_WINNT_AUTH_IDENTITY_UNICODE;

            if (credential != null)
            {
                if (credential.AccountName != null)
                {
                    this.UserLength = credential.AccountName.Length;
                    if (this.UserLength != 0)
                    {
                        this.User = Marshal.StringToHGlobalUni(credential.AccountName);
                    }
                }
                if (credential.DomainName != null)
                {
                    this.DomainLength = credential.DomainName.Length;
                    if (this.DomainLength != 0)
                    {
                        this.Domain = Marshal.StringToHGlobalUni(credential.DomainName);
                    }
                }
                if (credential.Password != null)
                {
                    this.PasswordLength = credential.Password.Length;
                    if (this.PasswordLength != 0)
                    {
                        this.Password = Marshal.StringToHGlobalUni(credential.Password);
                    }
                }
            }
        }
        /// <summary>
        /// Bind to SAMR RPC server.
        /// </summary>
        /// <param name="protocolSequence">
        /// RPC protocol sequence.
        /// </param>
        /// <param name="networkAddress">
        /// RPC network address.
        /// </param>
        /// <param name="endpoint">
        /// RPC endpoint.
        /// </param>
        /// <param name="transportCredential">
        /// If connect by SMB/SMB2, it's the security credential 
        /// used by under layer transport (SMB/SMB2). 
        /// If connect by TCP, this parameter is ignored.
        /// </param>
        /// <param name="securityContext">
        /// RPC security provider.
        /// </param>
        /// <param name="authenticationLevel">
        /// RPC authentication level.
        /// </param>
        /// <param name="timeout">
        /// Timeout
        /// </param>
        public void Bind(
            string protocolSequence,
            string networkAddress,
            string endpoint,
            AccountCredential transportCredential,
            ClientSecurityContext securityContext,
            RpceAuthenticationLevel authenticationLevel,
            TimeSpan timeout)
        {
            if (rpceClientTransport != null)
            {
                throw new InvalidOperationException("SAMR has already been binded.");
            }

            rpceTimeout = timeout;
            rpceClientTransport = new RpceClientTransport();

            rpceClientTransport.Bind(
                protocolSequence,
                networkAddress,
                endpoint,
                transportCredential,
                SamrUtility.SAMR_RPC_INTERFACE_UUID,
                SamrUtility.SAMR_RPC_INTERFACE_MAJOR_VERSION,
                SamrUtility.SAMR_RPC_INTERFACE_MINOR_VERSION,
                securityContext,
                authenticationLevel,
                false,
                rpceTimeout);
        }
        /// <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;
        }
        public virtual void Start(
            string localNetbiosName, int adapterIndex, int bufferSize,
            int maxSessions, int maxNames, AccountCredential credential)
        {
            if (localNetbiosName == null)
            {
                throw new ArgumentNullException("localNetbiosName");
            }

            NetbiosTransportConfig config = new NetbiosTransportConfig();
            config.Type = StackTransportType.Netbios;
            config.Role = Role.Server;
            config.AdapterIndex = (byte)adapterIndex;
            config.BufferSize = bufferSize;
            config.MaxSessions = maxSessions;
            config.MaxNames = maxNames;
            config.LocalNetbiosName = localNetbiosName;

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

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

            this.transportType = TransportType.NetBIOS;
        }
 /// <summary>
 /// <para>does not support this method.</para>
 /// start server and prepare to accept the connection from client.
 /// the under-layer transport is tcp/ip.
 /// </summary>
 /// <param name="listenPort">the port for serverto listen </param>
 /// <param name="credential">Credential to accept a connection.</param>
 /// <param name="ipAddress">server's ipAddress</param>
 /// <exception cref="NotSupportedException">does not support this method.</exception>
 public override void Start(ushort listenPort, AccountCredential credential, IPAddress ipAddress)
 {
     throw new NotSupportedException("does not support this method.");
 }
        /// <summary>
        /// Performs CredSSP authentication.
        /// </summary>
        /// <exception cref="IOException">Raised when attempting to read from/write to the remote connection which
        /// has been closed</exception>
        /// <exception cref="EndOfStreamException">Raised when the username or password doesn't match or authentication
        /// fails</exception>
        public void Authenticate()
        {
            // Authenticated already, do nothing
            if (isAuthenticated)
            {
                return;
            }

            credential = new AccountCredential(domain, userName, password);

            byte[] receivedBuffer = new byte[MaxBufferSize];
            int bytesReceived = 0;

            // Dispose the context as it may be timed out
            if (context != null)
            {
                context.Dispose();
            }
            context = new SspiClientSecurityContext(
                SecurityPackageType.CredSsp,
                credential,
                serverPrincipal,
                attribute,
                SecurityTargetDataRepresentation.SecurityNativeDrep);

            context.Initialize(null);
            // Get first token
            byte[] token = context.Token;
            // SSL handshake
            while (context.NeedContinueProcessing)
            {
                // Send handshake request
                clientStream.Write(token, 0, token.Length);
                // Get handshake resopnse
                bytesReceived = clientStream.Read(receivedBuffer, 0, receivedBuffer.Length);
                // The remote connection has been closed
                if (bytesReceived == 0)
                {
                    throw new EndOfStreamException("Authentication failed: remote connection has been closed.");
                }

                byte[] inToken = new byte[bytesReceived];
                Array.Copy(receivedBuffer, inToken, bytesReceived);
                // Get next token from response
                context.Initialize(inToken);
                token = context.Token;
            }
            // Send the last token, handshake over, CredSSP is established
            // Note if there're errors during authentication, an SSPIException will be raised
            // and isAuthentication will not be true.
            clientStream.Write(token, 0, token.Length);
            isAuthenticated = true;
        }
 /// <summary>
 /// start server and prepare to accept the connection from client.<para/>
 /// the under-layer transport is netbios.
 /// </summary>
 /// <param name="localNetbiosName">the local Netbios name. It is only used in NetBios tranport.</param>
 /// <param name="credential">Credential to accept a connection.</param>
 public abstract void Start(string localNetbiosName, AccountCredential credential);
        /// <summary>
        /// RPC bind to interface, using specified endpoint and authenticate provider.
        /// </summary>
        /// <param name="protocolSequence">RPC protocol sequence.</param>
        /// <param name="networkAddress">RPC network address.</param>
        /// <param name="endpoint">RPC endpoint.</param>
        /// <param name="transportCredential">
        /// If connect by SMB/SMB2, it's the security credential 
        /// used by underlayer transport (SMB/SMB2). 
        /// If connect by TCP, this parameter is ignored.
        /// </param>
        /// <param name="securityContext">RPC security provider.</param>
        /// <param name="authenticationLevel">RPC authentication level.</param>
        /// <param name="timeout">Timeout for bind and all future requests.</param>
        /// <exception cref="InvalidOperationException">
        /// Thrown when rpceClientTransport is not null.
        /// </exception>
        public void Bind(
            string protocolSequence,
            string networkAddress,
            string endpoint,
            AccountCredential transportCredential,
            ClientSecurityContext securityContext,
            RpceAuthenticationLevel authenticationLevel,
            TimeSpan timeout)
        {
            if (rpceClientTransport != null)
            {
                throw new InvalidOperationException("FSRVP has already been bind.");
            }

            rpceTimeout = timeout;

            rpceClientTransport = new RpceClientTransport();

            try
            {
                rpceClientTransport.Bind(
                    protocolSequence,
                    networkAddress,
                    endpoint,
                    transportCredential,
                    FsrvpUtility.FSRVP_INTERFACE_UUID,
                    FsrvpUtility.FSRVP_INTERFACE_MAJOR_VERSION,
                    FsrvpUtility.FSRVP_INTERFACE_MINOR_VERSION,
                    securityContext,
                    authenticationLevel,
                    true,
                    rpceTimeout);
            }
            catch
            {
                rpceClientTransport = null;
                throw;
            }
        }
 /// <summary>
 /// Bind to SAMR RPC server.
 /// </summary>
 /// <param name="protocolSequence">
 /// RPC protocol sequence.
 /// </param>
 /// <param name="networkAddress">
 /// RPC network address.
 /// </param>
 /// <param name="endpoint">
 /// RPC endpoint.
 /// </param>
 /// <param name="transportCredential">
 /// If connect by SMB/SMB2, it's the security credential 
 /// used by under layer transport (SMB/SMB2). 
 /// If connect by TCP, this parameter is ignored.
 /// </param>
 /// <param name="securityContext">
 /// RPC security provider.
 /// </param>
 /// <param name="authenticationLevel">
 /// RPC authentication level.
 /// </param>
 /// <param name="timeout">
 /// Timeout
 /// </param>
 public void Bind(
     string protocolSequence,
     string networkAddress,
     string endpoint,
     AccountCredential transportCredential,
     ClientSecurityContext securityContext,
     RpceAuthenticationLevel authenticationLevel,
     TimeSpan timeout)
 {
     rpc.Bind(protocolSequence,
                     networkAddress,
                     endpoint,
                     transportCredential,
                     securityContext,
                     authenticationLevel,
                     timeout);
 }
        internal static void AcquireCredentialsHandle(
            SecurityPackageType packageType,
            AccountCredential accountCredential,
            string serverPrincipal,
            uint fCredentialUse,
            out SecurityHandle credentialHandle)
        {
            string stringPackage = SspiUtility.GetPackageStringName(packageType);

            SecurityInteger expiryTime;
            SecurityWinntAuthIdentity authIdentity = new SecurityWinntAuthIdentity(accountCredential);
            IntPtr pAuthData = IntPtr.Zero;
            SchannelCred schannelCred = new SchannelCred();
            schannelCred.dwVersion = NativeMethods.SCHANNEL_CRED_VERSION;
            schannelCred.cCreds = 0;
            schannelCred.paCred = IntPtr.Zero;
            CredSspCred credSsp = new CredSspCred();

            switch (packageType)
            {
                case SecurityPackageType.Ntlm:
                case SecurityPackageType.Kerberos:
                case SecurityPackageType.Negotiate:
                    pAuthData = SspiUtility.CreateAuthData(authIdentity);
                    break;
                case SecurityPackageType.Schannel:
                    pAuthData = SspiUtility.CreateAuthData(schannelCred);
                    break;
                case SecurityPackageType.CredSsp:
                    credSsp.Type = CredSspSubmitType.CredsspSubmitBufferBoth;
                    credSsp.pSchannelCred = CreateAuthData(schannelCred);
                    credSsp.pSpnegoCred = CreateAuthData(authIdentity);
                    pAuthData = CreateAuthData(credSsp);
                    break;
                //default, if other values, exception will be thrown by GetPackageStringName.
                default:
                    throw new ArgumentException("Invlid packageType value.", "packageType");
            }

            uint result = NativeMethods.AcquireCredentialsHandle(
                serverPrincipal,
                stringPackage,
                fCredentialUse,
                IntPtr.Zero,
                pAuthData,
                IntPtr.Zero,
                IntPtr.Zero,
                out credentialHandle,
                out expiryTime);
            //Free memory
            switch (packageType)
            {
                case SecurityPackageType.Ntlm:
                case SecurityPackageType.Kerberos:
                case SecurityPackageType.Negotiate:
                    SspiUtility.FreeSecurityWinntAuthIdentity(authIdentity);
                    break;
                case SecurityPackageType.Schannel:
                    stringPackage = Schannel;
                    SspiUtility.FreeSchannelCred(schannelCred);
                    break;
                case SecurityPackageType.CredSsp:
                    SspiUtility.FreeSecurityWinntAuthIdentity(authIdentity);
                    SspiUtility.FreeSchannelCred(schannelCred);
                    SspiUtility.FreeCredSspCred(credSsp);
                    break;
                //default, if other values, exception will be thrown by GetPackageStringName.
                default:
                    throw new ArgumentException("Invlid packageType value.", "packageType");
            }
            Marshal.FreeHGlobal(pAuthData);

            if (result != NativeMethods.SEC_E_OK)
            {
                throw new SspiException("AquireCredentialsHandle failed", result);
            }
        }
        /// <summary>
        /// Start to listen on a named pipe.
        /// </summary>
        /// <param name="namedPipe">The name of named pipe to listen on.</param>
        /// <param name="credential">Credential to be used by underlayer SMB/SMB2 transport.</param>
        /// <exception cref="InvalidOperationException">
        /// Thrown when the server with the named pipe has been started.
        /// </exception>
        /// <param name="ipAddress">server's ipAddress</param>
        public virtual RpceServerContext StartNamedPipe(string namedPipe, AccountCredential credential, 
            IPAddress ipAddress)
        {
            namedPipe = namedPipe.ToUpper();

            lock (this.smbThreadLocker)
            {
                RpceServerContext serverContext = this.serverContextManager.LookupServerContext(
                    RpceUtility.RPC_OVER_NAMED_PIPE_PROTOCOL_SEQUENCE,
                    namedPipe);

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

                serverContext = new RpceServerContext(
                        RpceUtility.RPC_OVER_NAMED_PIPE_PROTOCOL_SEQUENCE,
                        namedPipe,
                        credential);

                this.serverContextManager.AddServerContext(serverContext);
                if (this.openedNamedPipeList == null)
                {
                    this.openedNamedPipeList = new List<string>();
                }
                this.openedNamedPipeList.Add(namedPipe);

                try
                {
                    if (this.smbTransport == null)
                    {
                        this.smbTransport = new Smb.SmbServerTransport();
                        this.smbTransport.Start(RpceUtility.NAMED_PIPE_PORT, credential, ipAddress);
                    }
                }
                catch
                {
                    this.serverContextManager.RemoveServerContext(serverContext);
                    this.openedNamedPipeList.Remove(namedPipe);
                    throw;
                }

                if (this.smbReceiveThread == null)
                {
                    this.smbReceiveThread = new Thread(SmbReceiveLoop);
                    this.smbReceiveThread.Start();
                }

                return serverContext;
            }
        }
        protected bool AccessShare(AccountCredential user, string sharePath)
        {
            bool accessSucceed = true;
            Smb2FunctionalClient client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            try
            {
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends NEGOTIATE message.");
                client.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends SESSION_SETUP message using account: {0}@{1}.", user.AccountName, user.DomainName);
                client.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, user, false);

                uint treeId;
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends TREE_CONNECT message to access share: {0}.", sharePath);
                client.TreeConnect(sharePath, out treeId, checker: (header, response) =>
                {
                    if (header.Status == Smb2Status.STATUS_SUCCESS)
                    {
                        BaseTestSite.Log.Add(LogEntryKind.Debug, "Access succeeded in TREE_CONNECT phase.");
                        accessSucceed = true;
                    }
                    else if (header.Status == Smb2Status.STATUS_ACCESS_DENIED)
                    {
                        BaseTestSite.Log.Add(LogEntryKind.Debug, "Access denied in TREE_CONNECT phase.");
                        accessSucceed = false;
                    }
                    else
                    {
                        BaseTestSite.Assert.Fail("Unexpected error code in TREE_CONNECT response: {0}", Smb2Status.GetStatusCode(header.Status));
                    }
                });

                if (!accessSucceed)
                {
                    client.LogOff();
                    return false;
                }

                FILEID fileId;
                Smb2CreateContextResponse[] createContexResponse;

                BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends CREATE request.");
                uint status = client.Create(
                    treeId,
                    null,
                    CreateOptions_Values.FILE_DIRECTORY_FILE,
                    out fileId,
                    out createContexResponse,
                    accessMask: AccessMask.FILE_READ_DATA | AccessMask.FILE_READ_ATTRIBUTES,
                    createDisposition: CreateDisposition_Values.FILE_OPEN,
                    checker: (header, response) =>
                    {
                        if (header.Status == Smb2Status.STATUS_SUCCESS)
                        {
                            BaseTestSite.Log.Add(LogEntryKind.Debug, "Access succeeded in CREATE phase.");
                            accessSucceed = true;
                        }
                        else if (header.Status == Smb2Status.STATUS_ACCESS_DENIED)
                        {
                            BaseTestSite.Log.Add(LogEntryKind.Debug, "Access denied in CREATE phase.");
                            accessSucceed = false;
                        }
                        else
                        {
                            BaseTestSite.Assert.Fail("Unexpected error code in CREATE response: {0}", Smb2Status.GetStatusCode(header.Status));
                        }
                    });

                if (status == Smb2Status.STATUS_SUCCESS)
                {
                    BaseTestSite.Log.Add(LogEntryKind.Debug, "Tear down the client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF.");
                    client.Close(treeId, fileId);
                }
                client.TreeDisconnect(treeId);
                client.LogOff();
            }
            finally
            {
                client.Disconnect();
            }
            return accessSucceed;
        }
 protected bool ShareExists(AccountCredential user, string sharePath)
 {
     BaseTestSite.Log.Add(LogEntryKind.Debug, "Test whether the specific share exists: {0}", sharePath);
     Smb2FunctionalClient clientAdmin;
     clientAdmin = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
     clientAdmin.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
     uint treeId;
     bool connected = ConnectToShare(clientAdmin, user, sharePath, out treeId);
     if (connected)
     {
         BaseTestSite.Log.Add(LogEntryKind.Debug, "Share exists: {0}", sharePath);
         clientAdmin.TreeDisconnect(treeId);
         clientAdmin.LogOff();
     }
     else
     {
         BaseTestSite.Log.Add(LogEntryKind.Debug, "Share does not exist: {0}", sharePath);
     }
     clientAdmin.Disconnect();
     return connected;
 }
        protected bool ConnectToShare(Smb2FunctionalClient client, AccountCredential user, string sharePath, out uint treeId)
        {
            BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends NEGOTIATE message.");
            client.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            AccountCredential accountCredential = user;
            BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends SESSION_SETUP message using account: {0}@{1}.", accountCredential.AccountName, accountCredential.DomainName);
            client.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, accountCredential, false);

            BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends TREE_CONNECT message to access share: {0}.", sharePath);
            uint status = client.TreeConnect(sharePath, out treeId, checker: (header, response) => { });
            if (status == Smb2Status.STATUS_SUCCESS)
            {
                return true;
            }
            if (status == Smb2Status.STATUS_BAD_NETWORK_NAME)
            {
                return false;
            }
            throw new Exception(string.Format("Share detection failed with unexpected error: {0}", Smb2Status.GetStatusCode(status)));
        }
        /// <summary>
        /// Bind RPC server.
        /// </summary>
        /// <param name="swnClient">SWN rpc client</param>
        /// <param name="networkAddress">RPC network address</param>
        /// <param name="domainName">Domain name</param>
        /// <param name="userName">User name</param>
        /// <param name="password">Password</param>
        /// <param name="securityPackage">Security package</param>
        /// <param name="authLevel">Authentication level</param>
        /// <param name="timeout">Timeout</param>
        /// <param name="serverComputerName">ServerComputerName</param>
        /// <returns>Return true if success, otherwise return false</returns>
        public static bool BindServer(SwnClient swnClient, IPAddress networkAddress, string domainName, string userName, string password,
            SecurityPackageType securityPackage, RpceAuthenticationLevel authLevel, TimeSpan timeout,string serverComputerName = null)
        {
            AccountCredential accountCredential = new AccountCredential(domainName, userName, password);
            string cifsServicePrincipalName = string.Empty;
            if (!string.IsNullOrEmpty(serverComputerName))
            {
                cifsServicePrincipalName = "cifs/" + serverComputerName;
            }
            else
            {
                IPHostEntry hostEntry = null;
                try
                {
                    hostEntry = Dns.GetHostEntry(networkAddress);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("Failed to resolve network address {0} with exception: {1}", networkAddress.ToString(), ex.Message));
                }

                if (hostEntry != null && !string.IsNullOrEmpty(hostEntry.HostName))
                {
                    cifsServicePrincipalName = "cifs/" + hostEntry.HostName;
                }
                else
                {
                    throw new Exception("Failed to get HostName from network address " + networkAddress.ToString());
                }
            }
            ClientSecurityContext securityContext =
                new SspiClientSecurityContext(
                    securityPackage,
                    accountCredential,
                    cifsServicePrincipalName,
                    ClientSecurityContextAttribute.Connection
                        | ClientSecurityContextAttribute.DceStyle
                        | ClientSecurityContextAttribute.Integrity
                        | ClientSecurityContextAttribute.ReplayDetect
                        | ClientSecurityContextAttribute.SequenceDetect
                        | ClientSecurityContextAttribute.UseSessionKey,
                    SecurityTargetDataRepresentation.SecurityNativeDrep);

            try
            {
                //Bind
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Start to Bind RPC to {0}.", networkAddress.ToString());
                swnClient.SwnBind(networkAddress.ToString(), accountCredential, securityContext, authLevel, timeout);
            }
            catch (Exception ex)
            {
                BaseTestSite.Log.Add(LogEntryKind.Debug,
                    "Bind server {0} failed. Exception: {1}",
                    networkAddress.ToString(),
                    ex.Message);
                swnClient.SwnUnbind(timeout);
                return false;
            }

            BaseTestSite.Log.Add(LogEntryKind.Debug, "Bind server {0} successfully.", networkAddress.ToString());
            return true;
        }
 /// <summary>
 /// start server and prepare to accept the connection from client.<para/>
 /// the under-layer transport is tcp/ip.
 /// </summary>
 /// <param name="listenPort">the port for serverto listen </param>
 /// <param name="credential">Credential to accept a connection.</param>
 /// <param name="ipAddress">server's ipAddress</param>
 public abstract void Start(ushort listenPort, AccountCredential credential, IPAddress ipAddress);
 /// <summary>
 /// <para>Start the server, use NetBIOS Extended User Interface as transport.</para>
 /// <para>Please customize Context before start this service. All of those properties will be used.</para>
 /// <para>If config.serverNetbiosName is null or empty, Context.ServerName will be used,
 /// which by default is the NetBIOS name of this local computer.</para>
 /// </summary>
 /// <param name="credential">Credential to accept a connection.</param>
 public virtual void Start(AccountCredential credential)
 {
     this.context.AccountCredentials.Add(credential);
     this.transport.Start();
     this.isRunning = true;
 }
        /// <summary>
        /// RPC bind over named pipe, using well-known endpoint "\\pipe\\FssagentRpc".
        /// </summary>
        /// <param name="serverName">FSRVP server machine name.</param>
        /// <param name="transportCredential">
        /// If connect by SMB/SMB2, it's the security credential 
        /// used by underlayer transport (SMB/SMB2). 
        /// If connect by TCP, this parameter is ignored.
        /// </param>
        /// <param name="securityContext">
        /// Security provider for RPC. 
        /// Set the value to null to disable authentication.
        /// </param>
        /// <param name="timeout">Timeout for bind and all future requests.</param>
        /// <returns>Return true if success, otherwise return false.</returns>
        /// <exception cref="ArgumentNullException">
        /// Thrown when serverName is null.
        /// </exception>
        public void BindOverNamedPipe(
            string serverName,
            AccountCredential transportCredential,
            ClientSecurityContext securityContext,
            TimeSpan timeout)
        {
            if (serverName == null)
            {
                throw new ArgumentNullException("serverName");
            }

            Bind(
                RpceUtility.RPC_OVER_NAMED_PIPE_PROTOCOL_SEQUENCE,
                serverName,
                FsrvpUtility.FSRVP_NAMED_PIPE,
                transportCredential,
                securityContext,
                context.AuthenticationLevel,
                timeout);
        }
        /// <summary>
        /// Constructor. Convert account 
        /// </summary>
        /// <param name="credential">Account credential</param>
        public SecurityWinntAuthIdentity(AccountCredential credential)
        {
            this.User = IntPtr.Zero;
            this.UserLength = 0;
            this.Domain = IntPtr.Zero;
            this.DomainLength = 0;
            this.Password = IntPtr.Zero;
            this.PasswordLength = 0;
            this.Flags = NativeMethods.SEC_WINNT_AUTH_IDENTITY_UNICODE;

            if (credential != null)
            {
                if (credential.AccountName != null)
                {
                    this.UserLength = credential.AccountName.Length;
                    if (this.UserLength != 0)
                    {
                        this.User = Marshal.StringToHGlobalUni(credential.AccountName);
                    }
                }
                if (credential.DomainName != null)
                {
                    this.DomainLength = credential.DomainName.Length;
                    if (this.DomainLength != 0)
                    {
                        this.Domain = Marshal.StringToHGlobalUni(credential.DomainName);
                    }
                }
                if (credential.Password != null)
                {
                    this.PasswordLength = credential.Password.Length;
                    if (this.PasswordLength != 0)
                    {
                        this.Password = Marshal.StringToHGlobalUni(credential.Password);
                    }
                }
            }
        }
        public SspiClientSecurityContext(
            SecurityPackageType packageType,
            AccountCredential clientCredential,
            string serverPrincipal,
            ClientSecurityContextAttribute contextAttributes,
            SecurityTargetDataRepresentation targetDataRep)
        {
            this.packageType = packageType;
            this.serverPrincipalName = serverPrincipal;
            this.securityContextAttributes = contextAttributes;
            this.targetDataRepresentaion = targetDataRep;

            SspiUtility.AcquireCredentialsHandle(
                packageType,
                clientCredential,
                serverPrincipal,
                NativeMethods.SECPKG_CRED_OUTBOUND,
                out this.credentialHandle);
        }
 /// <summary>
 /// start server and prepare to accept the connection from client.<para/>
 /// the under-layer transport is netbios.
 /// </summary>
 /// <param name="localNetbiosName">the local Netbios name. It is only used in NetBios transport.</param>
 /// <param name="credential">Credential to accept a connection.</param>
 public override void Start(string localNetbiosName, AccountCredential credential)
 {
     this.cifsServer.Context.ServerName = localNetbiosName;
     this.cifsServer.Start(credential);
 }
        /// <summary>
        /// Common method used to connect to target server, including the following message sequences:
        /// 1. Negotiate
        /// 2. Session Setup
        /// 3. Tree Connect
        /// </summary>
        /// <param name="smb2Dialect"></param>
        /// <param name="client"></param>
        /// <param name="clientGuid"></param>
        /// <param name="account"></param>
        /// <param name="connectShareType"></param>
        /// <param name="treeId"></param>
        /// <param name="clientBeforeDisconnection"></param>
        protected virtual void Connect(DialectRevision smb2Dialect, Smb2FunctionalClient client, Guid clientGuid, AccountCredential account, ConnectShareType connectShareType, out uint treeId, Smb2FunctionalClient clientBeforeDisconnection)
        {
            DialectRevision[] requestDialect = Smb2Utility.GetDialects(smb2Dialect);
            Capabilities_Values clientCapabilities = Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES;
            SecurityMode_Values clientSecurityMode = SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED;

            IPAddress targetIPAddress = (connectShareType == ConnectShareType.CAShare) ? testConfig.CAShareServerIP : testConfig.SutIPAddress;
            string targetServer = (connectShareType == ConnectShareType.CAShare) ? testConfig.CAShareServerName : testConfig.SutComputerName;

            client.ConnectToServer(TestConfig.UnderlyingTransport, targetServer, targetIPAddress);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends NEGOTIATE request.", clientGuid);
            client.Negotiate(
                requestDialect,
                TestConfig.IsSMB1NegotiateEnabled,
                clientSecurityMode,
                clientCapabilities,
                clientGuid);

            if (null != clientBeforeDisconnection)
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends SESSION_SETUP request to reconnect to the previous session.", clientGuid);
                client.ReconnectSessionSetup(
                    clientBeforeDisconnection,
                    testConfig.DefaultSecurityPackage,
                    targetServer,
                    account,
                    testConfig.UseServerGssToken);
            }
            else
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends SESSION_SETUP request.", clientGuid);
                client.SessionSetup(
                    testConfig.DefaultSecurityPackage,
                    targetServer,
                    account,
                    testConfig.UseServerGssToken);
            }

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends TREE_CONNECT request.", clientGuid);
            client.TreeConnect(
                durableHandleUncSharePath,
                out treeId,
                checker: (header, response) =>
                {
                    BaseTestSite.Log.Add(
                        LogEntryKind.Debug,
                        "Capabilities in TREE_CONNECT response: {0}", response.Capabilities);

                    BaseTestSite.Assert.AreEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "{0} should be successful", header.Command);

                    if (connectShareType == ConnectShareType.CAShare)
                    {
                        BaseTestSite.Assert.AreEqual(
                            Share_Capabilities_Values.SHARE_CAP_CONTINUOUS_AVAILABILITY,
                            Share_Capabilities_Values.SHARE_CAP_CONTINUOUS_AVAILABILITY & response.Capabilities,
                            "The share should have SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY capability");
                    }

                    if (connectShareType == ConnectShareType.BasicShare)
                    {
                        BaseTestSite.Assert.AreNotEqual(
                            Share_Capabilities_Values.SHARE_CAP_CONTINUOUS_AVAILABILITY,
                            Share_Capabilities_Values.SHARE_CAP_CONTINUOUS_AVAILABILITY & response.Capabilities,
                            "The share should not have SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY capability");
                    }
                });
        }
        private void InnerBind(
            string protocolSequence,
            string networkAddress,
            string endpoint,
            AccountCredential transportCredential,
            ClientSecurityContext securityContext)
        {
            if (RpceClientTransport != null)
            {
                throw new InvalidOperationException("SRVS has already been bind");
            }

            RpceClientTransport = new RpceClientTransport();

            try
            {
                RpceClientTransport.Bind(
                    protocolSequence,
                    networkAddress,
                    endpoint,
                    transportCredential,
                    SrvsUtility.SRVS_INTERFACE_UUID,
                    SrvsUtility.SRVS_INTERFACE_MAJOR_VERSION,
                    SrvsUtility.SRVS_INTERFACE_MINOR_VERSION,
                    securityContext,
                    AuthenticationLevel,
                    true,
                    RpceTimeout);
            }
            catch
            {
                RpceClientTransport = null;
                throw;
            }
        }
        /// <summary>
        /// Connect to server.
        /// </summary>
        /// <param name="client">Fsrvp client.</param>
        /// <param name="server">The name of server.</param>
        /// <returns>Return true if success, otherwise return false.</returns>
        private bool ConnectServer(ref FsrvpClient client, string server)
        {
            AccountCredential accountCredential =
                new AccountCredential(TestConfig.DomainName, TestConfig.UserName, TestConfig.UserPassword);

            ClientSecurityContext securityContext =
                new SspiClientSecurityContext(
                    TestConfig.DefaultSecurityPackage,
                    accountCredential,
                    Smb2Utility.GetCifsServicePrincipalName(server),
                    ClientSecurityContextAttribute.Connection
                        | ClientSecurityContextAttribute.DceStyle
                        | ClientSecurityContextAttribute.Integrity
                        | ClientSecurityContextAttribute.ReplayDetect
                        | ClientSecurityContextAttribute.SequenceDetect
                        | ClientSecurityContextAttribute.UseSessionKey,
                    SecurityTargetDataRepresentation.SecurityNativeDrep);

            // This indicates that the RPC message is just integrity-protected.
            client.Context.AuthenticationLevel = TestConfig.DefaultRpceAuthenticationLevel;

            try
            {
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Connect to server {0}.", server);
                client.BindOverNamedPipe(server, accountCredential, securityContext,
                    new TimeSpan(0, 0, (int)FsrvpUtility.FSRVPTimeoutInSeconds));
            }
            catch (Exception ex)
            {
                BaseTestSite.Log.Add(LogEntryKind.Debug,
                    "Connect to server {0} failed. Exception: {1}",
                    server,
                    ex.Message);
                client.Unbind(TestConfig.Timeout);
                return false;
            }

            BaseTestSite.Log.Add(LogEntryKind.Debug, "Connect to server {0} successfully.", server);
            return true;
        }
        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);
        }