Ejemplo n.º 1
0
        public void CreateProfile(String ssid, SecurityModes securityMode, Byte[] key = null, Byte keyIndex = 0, Byte channel = 0)
        {
            if ((key == null || key.Length == 0) && securityMode != SecurityModes.Open)
            {
                throw new ArgumentException("Invalid profile informations");
            }
            var pf = new ConnectionProfile(ssid, securityMode, key, keyIndex, channel);

            if (_profilesCount == 1)
            {
                Reset(ResetModes.Hard);
            }
            Init(pf.Num);
        }
Ejemplo n.º 2
0
            public ConnectionProfile(String pSSID, SecurityModes pSecurityMode, Byte[] pKey = null, Byte pKeyIndex = 0, Byte pChannel = 0)
            {
                if (_profilesCount == 2)
                {
                    throw new InvalidOperationException();
                }
                Num          = _profilesCount;
                SSID         = pSSID;
                SecurityMode = pSecurityMode;
                SecurityKey  = pKey;
                KeyIndex     = pKeyIndex;
                Channel      = pChannel;

                _profiles[_profilesCount] = this;
                _profilesCount++;
            }
Ejemplo n.º 3
0
        private bool SmbUpdateContextWithResponsePacket(SmbClientConnection connection, SmbPacket response)
        {
            if (response == null)
            {
                return false;
            }

            int connectionId = connection.ConnectionId;

            SmbHeader smbHeader = response.SmbHeader;

            // only process the response packet.
            if (response.PacketType != SmbPacketType.BatchedResponse
                && response.PacketType != SmbPacketType.SingleResponse)
            {
                return false;
            }

            // packet status
            SmbStatus packetStatus = (SmbStatus)smbHeader.Status;

            // filter error packet
            if (packetStatus != SmbStatus.STATUS_SUCCESS &&
                    packetStatus != SmbStatus.STATUS_MORE_PROCESSING_REQUIRED &&
                    packetStatus != SmbStatus.STATUS_BUFFER_OVERFLOW)
            {
                return false;
            }

            // process each special command
            switch (smbHeader.Command)
            {
                #region Negotiate Response

                case SmbCommand.SMB_COM_NEGOTIATE:

                    // implicit ntlm, decode using cifs sdk.
                    if (!smbClient.Capability.IsSupportsExtendedSecurity)
                    {
                        return false;
                    }

                    // down cast to negotiate response packet.
                    SmbNegotiateResponsePacket negotiate = response as SmbNegotiateResponsePacket;

                    // set negotiate flag
                    connection.NegotiateSent = true;

                    #region update security mode

                    SecurityModes securityModes = negotiate.SmbParameters.SecurityMode;

                    if (SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_ENABLED
                        == (securityModes & SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_ENABLED))
                    {
                        connection.ServerSigningState = SignState.ENABLED;
                    }
                    else if (SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_REQUIRED
                        == (securityModes & SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_REQUIRED))
                    {
                        connection.ServerSigningState = SignState.REQUIRED;
                    }
                    else
                    {
                        connection.ServerSigningState = SignState.DISABLED;
                    }

                    if (SecurityModes.NEGOTIATE_USER_SECURITY
                        == (securityModes & SecurityModes.NEGOTIATE_USER_SECURITY))
                    {
                        connection.UsesSharePasswords = false;
                    }
                    else
                    {
                        connection.UsesSharePasswords = true;
                    }

                    if (SecurityModes.NEGOTIATE_ENCRYPT_PASSWORDS
                        == (securityModes & SecurityModes.NEGOTIATE_ENCRYPT_PASSWORDS))
                    {
                        connection.IsClientEncryptPasswords = true;
                    }
                    else
                    {
                        connection.IsClientEncryptPasswords = false;
                    }

                    // update IsSignActive using the combination of the client's 
                    // MessageSigningPolicy and the connection's ServerSigningState
                    smbClient.Context.UpdateSigningActive(connection);

                    #endregion

                    #region update server capabilities

                    connection.ServerCapabilities = (Capabilities)negotiate.SmbParameters.Capabilities;

                    if (Capabilities.CAP_INFOLEVEL_PASSTHRU
                        == (connection.ServerCapabilities & Capabilities.CAP_INFOLEVEL_PASSTHRU))
                    {
                        smbClient.Capability.IsUsePassThrough = true;
                    }

                    #endregion

                    #region update maxbuffersize

                    connection.MaxBufferSize = negotiate.SmbParameters.MaxBufferSize;

                    #endregion

                    this.AddOrUpdateConnection(connection);

                    break;

                #endregion

                #region Session Setup Response

                case SmbCommand.SMB_COM_SESSION_SETUP_ANDX:

                    // implicit ntlm, decode using cifs sdk.
                    if (!smbClient.Capability.IsSupportsExtendedSecurity)
                    {
                        return false;
                    }

                    // the session to operation on.
                    SmbClientSession session = null;

                    // down-case the packet
                    SmbSessionSetupAndxResponsePacket packet = response as SmbSessionSetupAndxResponsePacket;

                    // if session exists, use it.
                    if (this.GetSession(connectionId, smbHeader.Uid) != null)
                    {
                        session = new SmbClientSession(this.GetSession(connectionId, smbHeader.Uid));
                    }
                    else
                    {
                        session = new SmbClientSession();
                    }

                    // if success, update context and session key.
                    if (packetStatus == SmbStatus.STATUS_SUCCESS)
                    {
                        // if spng, the SessionKey is null and the SecurityBlob from server contains data
                        // in this situation, need to initialize the SecurityBlob of server to generate the SessionKey
                        if (connection.GssApi.SessionKey == null
                            && packet.SecurityBlob != null && packet.SecurityBlob.Length > 0)
                        {
                            connection.GssApi.Initialize(packet.SecurityBlob);
                        }

                        // get session key and store in the context
                        session.SessionKey = connection.GssApi.SessionKey;

                        // reset the gss api of connection
                        connection.GssApi = null;

                        // reset the securityblob when success
                        packet.SecurityBlob = null;
                    }

                    // update the security blob from server
                    connection.SecurityBlob = packet.SecurityBlob;
                    this.AddOrUpdateConnection(connection);

                    // update session
                    session.SessionUid = smbHeader.Uid;
                    session.ConnectionId = connectionId;

                    this.AddOrUpdateSession(session);

                    break;

                #endregion

                default:
                    return false;
            }

            return true;
        }
        /// <summary>
        /// Create SMB_COM_NEGOTIATE response 
        /// </summary>
        /// <param name="connection">the connection identified the client</param>
        /// <param name = "securityMode">
        /// An 8-bit field, indicating the security modes supported or REQUIRED by the server 
        /// </param>
        /// <param name = "maxBufferSize">
        /// The maximum size, in bytes, of the largest SMB message the server can receive. This is the size of the  
        /// SMB message that the client MAY send to the server. SMB message size includes the size of the  SMB  
        /// parameter, and data blocks. This size does not include any  transport-layer framing or other  data. The 
        /// server MUST provide a MaxBufferSize of 1024 bytes (1Kbyte) or larger. If CAP_RAW_MODE is  then the 
        /// SMB_COM_WRITE_RAW command can bypass the MaxBufferSize limit. Otherwise, SMB messages sent to  server  
        /// MUST have a total size less than or equal to the MaxBufferSize value. This includes AndX chained 
        /// </param>
        /// <param name="maxMpxCount">
        /// The maximum number of outstanding SMB operations the server supports. This value includes existing 
        /// OpLocks, the NT_TRANSACT_NOTIFY_CHANGE subcommand, and any other command that are pending on the server. 
        /// If the negotiated MaxMpxCount is one, then OpLock support MUST be disabled for this session. The 
        /// MaxMpxCount MUST be greater than zero. This parameter has no specific relationship to the 
        /// SMB_COM_READ_MPX and SMB_COM_WRITE_MPX commands. 
        /// </param>
        /// <returns>a smb negotiate response packet </returns>
        /// <exception cref="ArgumentNullException">connection must not be null</exception>
        /// <exception cref="NotImplementedException">the security package is invalid</exception>
        public virtual SmbNegotiateResponsePacket CreateSmbComNegotiateResponse(
            SmbServerConnection connection,
            SecurityModes securityMode,
            uint maxBufferSize,
            ushort maxMpxCount)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            SmbNegotiateResponsePacket packet = new SmbNegotiateResponsePacket();

            // create smb packet header
            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(
                SmbCommand.SMB_COM_NEGOTIATE, connection.ProcessId, connection.MessageId, 0, 0,
                (SmbFlags)connection.Capability.Flag, (SmbFlags2)connection.Capability.Flags2);

            // update smb parameters
            SMB_COM_NEGOTIATE_NtLanManagerResponse_SMB_Parameters smbParameters = packet.SmbParameters;

            ushort dialectIndex = 0x00;
            byte wordCount = 0x00;
            connection.GetPreferedDialectIndex(out dialectIndex, out wordCount);

            smbParameters.WordCount = wordCount;
            smbParameters.DialectIndex = dialectIndex;
            smbParameters.SecurityMode = securityMode;
            smbParameters.MaxBufferSize = maxBufferSize;
            smbParameters.MaxMpxCount = maxMpxCount;
            smbParameters.Capabilities = connection.ServerCapabilities;
            smbParameters.SystemTime.Time = (ulong)DateTime.Now.ToFileTime();

            // update smb data
            SMB_COM_NEGOTIATE_NtLanManagerResponse_SMB_Data smbData = packet.SmbData;

            if (connection.GssApi == null)
            {
                connection.GssApi = new SspiServerSecurityContext(
                    SecurityPackageType.Negotiate,
                    this.credential,
                    "cifs/" + Environment.MachineName,
                    ServerSecurityContextAttribute.Connection,
                    SecurityTargetDataRepresentation.SecurityNetworkDrep);
            }

            // to generate the token.
            connection.GssApi.Accept(null);

            smbData.SecurityBlob = connection.GssApi.Token;

            // update smbData.ByteCount
            smbData.ByteCount = 0;
            smbData.ByteCount += (ushort)CifsMessageUtils.GetSize<Guid>(smbData.ServerGuid);
            if (smbData.SecurityBlob != null)
            {
                smbData.ByteCount += (ushort)smbData.SecurityBlob.Length;
            }

            // store the parameters and data to packet.
            packet.SmbParameters = smbParameters;
            packet.SmbData = smbData;

            return packet;
        }
        /// <summary>
        /// Create SMB_COM_NEGOTIATE response 
        /// </summary>
        /// <param name="connection">the connection identified the client</param>
        /// <param name = "securityMode">
        /// An 8-bit field, indicating the security modes supported or REQUIRED by the server 
        /// </param>
        /// <param name = "maxBufferSize">
        /// The maximum size, in bytes, of the largest SMB message the servercan receive. This is the size of the  SMB 
        /// message that the clientMAY send to the server. SMB message size includes the size of the SMB header,  and 
        /// data blocks. This size does not include any transport-layer framing or other transport-layer data.  server 
        /// MUSTprovide a MaxBufferSize of 1024 bytes (1Kbyte) or larger.If CAP_RAW_MODE is negotiated, then  
        /// SMB_COM_WRITE_RAW commandcan bypass the MaxBufferSize limit. Otherwise, SMB messages sent to the server  
        /// have a total size less than or equal to the MaxBufferSize value.This includes AndX chained  default 
        /// MaxBufferSize on Windows NT server is 4356 bytes(4KB + 260Bytes) if the server has 512MB of  or less. If 
        /// the server has more than 512MB of memory, then the default MaxBufferSize is 16644 bytes (16KB  260Bytes). 
        /// Windows NT servers always use a MaxBufferSize value that is a multiple of four (4). The  can be configured 
        /// through the following registry setting: 
        /// </param>
        /// <param name="maxMpxCount">
        /// The maximum number of outstanding SMB operations the server
        /// supports. This value includes existing OpLocks, 
        /// the NT_TRANSACT_NOTIFY_CHANGE subcommand, and any other command 
        /// that are pending on the server. If the negotiated MaxMpxCount is one, 
        /// then OpLock support MUST be disabled for this session. The MaxMpxCount
        /// MUST be greater than zero. This parameter has no specific 
        /// relationship to the SMB_COM_READ_MPX and SMB_COM_WRITE_MPX commands. 
        /// </param>
        /// <returns>a smb implicit ntlm negotiate response packet </returns>
        /// <exception cref="ArgumentNullException">connection must not be null</exception>
        public virtual SmbNegotiateImplicitNtlmResponsePacket CreateSmbComNegotiateImplicitNtlmResponse(
            SmbServerConnection connection,
            SecurityModes securityMode,
            uint maxBufferSize,
            ushort maxMpxCount)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            Cifs.SmbNegotiateResponsePacket packet = new Cifs.SmbNegotiateResponsePacket();

            // create smb packet header
            packet.SmbHeader = CifsMessageUtils.CreateSmbHeader(
                SmbCommand.SMB_COM_NEGOTIATE, connection.ProcessId, connection.MessageId, 0, 0,
                (SmbFlags)connection.Capability.Flag, (SmbFlags2)connection.Capability.Flags2);

            // update smb parameters
            Cifs.SMB_COM_NEGOTIATE_NtLanManagerResponse_SMB_Parameters smbParameters = packet.SmbParameters;

            ushort dialectIndex = 0x00;
            byte wordCount = 0x00;
            connection.GetPreferedDialectIndex(out dialectIndex, out wordCount);

            smbParameters.WordCount = wordCount;
            smbParameters.DialectIndex = dialectIndex;
            smbParameters.SecurityMode = securityMode;
            smbParameters.MaxBufferSize = maxBufferSize;
            smbParameters.MaxMpxCount = maxMpxCount;
            smbParameters.Capabilities = (Cifs.Capabilities)connection.ServerCapabilities;
            smbParameters.SystemTime.Time = (ulong)connection.SystemTime;
            smbParameters.ChallengeLength = (byte)connection.NtlmEncryptionKey.Length;

            // update smb data
            Cifs.SMB_COM_NEGOTIATE_NtLanManagerResponse_SMB_Data smbData = packet.SmbData;

            smbData.Challenge = connection.NtlmEncryptionKey;

            // update smbData.ByteCount
            smbData.ByteCount = 0;
            if (smbData.Challenge != null)
            {
                smbData.ByteCount += (ushort)smbData.Challenge.Length;
            }
            if (smbData.DomainName != null)
            {
                smbData.ByteCount += (ushort)smbData.DomainName.Length;
            }

            // store the parameters and data to packet.
            packet.SmbParameters = smbParameters;
            packet.SmbData = smbData;

            return new SmbNegotiateImplicitNtlmResponsePacket(packet);
        }
        public SmbNegotiateResponsePacket CreateNegotiateResponse(
            CifsServerPerConnection connection,
            SmbNegotiateRequestPacket request,
            SecurityModes securityMode)
        {
            SmbNegotiateResponsePacket response = new SmbNegotiateResponsePacket();
            response.SmbHeader = CifsMessageUtils.CreateSmbHeader(connection, request);

            Stack<string> dialectStrings = new Stack<string>();

            for (int offset = 0; offset < request.SmbData.Dialects.Length; offset++)
            {
                string dialectString = CifsMessageUtils.ToSmbString(request.SmbData.Dialects, offset, true);
                dialectStrings.Push(dialectString);
                offset += sizeof(byte) + dialectString.Length;
            }

            while(dialectStrings.Count > 0)
            {
                string dialectString = dialectStrings.Pop();
                if(dialectString == CifsMessageUtils.DIALECT_NTLANMAN)
                {
                    SMB_COM_NEGOTIATE_NtLanManagerResponse_SMB_Parameters smbParameters = response.SmbParameters;
                    smbParameters.WordCount = (byte)((Marshal.SizeOf(response.SmbParameters) - sizeof(byte)) / 2);
                    smbParameters.DialectIndex = (ushort)dialectStrings.Count;
                    smbParameters.SecurityMode = securityMode;
                    smbParameters.MaxMpxCount = (ushort)this.context.MaxMpxCount;
                    smbParameters.MaxNumberVcs = (ushort)this.context.MaxNumberVcs;
                    smbParameters.MaxBufferSize = (ushort)this.context.MaxBufferSize;
                    smbParameters.MaxRawSize = (ushort)this.context.MaxRawSize;
                    smbParameters.SessionKey = 0;
                    smbParameters.Capabilities = this.context.Capabilities;
                    FileTime fileTime = new FileTime();
                    fileTime.Time = (ulong)DateTime.Now.ToFileTime();
                    smbParameters.SystemTime = fileTime;

                    smbParameters.ServerTimeZone = (short)TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).Minutes;
                    smbParameters.ChallengeLength = (byte)connection.NTLMChallenge.Length;
                    response.SmbParameters = smbParameters;

                    SMB_COM_NEGOTIATE_NtLanManagerResponse_SMB_Data smbData = response.SmbData;
                    smbData.Challenge = connection.NTLMChallenge;
                    smbData.DomainName = CifsMessageUtils.ToSmbStringBytes(this.context.DomainName, true);
                    smbData.ByteCount = (ushort)(smbData.Challenge.Length + smbData.DomainName.Length);
                    response.SmbData = smbData;

                    return response;
                }
                else if (dialectString == CifsMessageUtils.DIALECT_PCLAN
                    || dialectString == CifsMessageUtils.DIALECT_PCNETWORK_PROGRAM)
                {
                    SMB_COM_NEGOTIATE_NtLanManagerResponse_SMB_Parameters smbParameters = response.SmbParameters;
                    smbParameters.WordCount = 0x1;
                    smbParameters.DialectIndex = (ushort)dialectStrings.Count;
                    response.SmbParameters = smbParameters;

                    SMB_COM_NEGOTIATE_NtLanManagerResponse_SMB_Data smbData = response.SmbData;
                    smbData.Challenge = connection.NTLMChallenge;
                    smbData.DomainName = CifsMessageUtils.ToSmbStringBytes(this.context.DomainName, true);
                    smbData.ByteCount = (ushort)(smbData.Challenge.Length + smbData.DomainName.Length);
                    response.SmbData = smbData;

                    return response;
                }
            }

            throw new NotSupportedException("None of these dialects is supported.");
        }
        /// <summary>
        /// Connect share specified by shareName, this function does not issue tcp or netbios
        /// connect, it does Negotiate -> SessionSetup -> TreeConnect
        /// </summary>
        /// <param name="serverName">The server name</param>
        /// <param name="domain">The domain</param>
        /// <param name="userName">The user name</param>
        /// <param name="password">The password</param>
        /// <param name="shareName">The share name</param>
        /// <param name="securityPackage">The security package</param>
        private void InternalConnectShare(string serverName, string domain,
                                          string userName, string password, string shareName, SecurityPackageType securityPackage)
        {
            SmbPacket request;
            SmbPacket response;
            uint      status;

            // Negotiate:
            request = this.smbClient.CreateNegotiateRequest(
                defaultSignState, new string[] { DialectNameString.NTLANMAN });
            response = this.SendAndExpectSmbPacket(request, internalTimeout, out status);

            if (status != 0)
            {
                throw new InvalidOperationException("Negotiate Failed. ErrorCode: " + status);
            }
            SecurityModes securityMode = (response as SmbNegotiateResponsePacket).SmbParameters.SecurityMode;

            this.isSignRequired = (securityMode & SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)
                                  == SecurityModes.NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;

            SmbSecurityPackage secPkg;

            switch (securityPackage)
            {
            case SecurityPackageType.Ntlm:
                secPkg = SmbSecurityPackage.NTLM;
                break;

            case SecurityPackageType.Kerberos:
                secPkg = SmbSecurityPackage.Kerberos;
                break;

            case SecurityPackageType.Negotiate:
                secPkg = SmbSecurityPackage.Negotiate;
                break;

            default:
                throw new ArgumentException("Unsupported securityPackage: " + securityPackage.ToString());
            }


            // Session setup:
            request = this.smbClient.CreateFirstSessionSetupRequest(secPkg, serverName, domain, userName,
                                                                    password);
            response = this.SendAndExpectSmbPacket(request, internalTimeout, out status);

            while (status != 0)
            {
                if ((int)status == (int)SmbStatus.STATUS_MORE_PROCESSING_REQUIRED)
                {
                    this.uid = (response as SmbSessionSetupAndxResponsePacket).SmbHeader.Uid;
                    request  = this.smbClient.CreateSecondSessionSetupRequest(this.uid, secPkg);
                    response = this.SendAndExpectSmbPacket(request, internalTimeout, out status);
                }
                else
                {
                    throw new InvalidOperationException("Session Setup Failed. ErrorCode: " + status);
                }
            }
            this.uid = (response as SmbSessionSetupAndxResponsePacket).SmbHeader.Uid;

            if (isSignRequired)
            {
                CifsClientPerSession session = this.smbClient.Context.GetSession(
                    this.smbClient.Context.Connection.ConnectionId, this.uid);
                this.sessionKey = session.SessionKey;
            }

            // Tree connect:
            string sharePath = "\\\\" + serverName + '\\' + shareName;

            request = this.smbClient.CreateTreeConnectRequest(this.uid, sharePath);

            if (this.isSignRequired)
            {
                request.Sign(this.NextSequenceNumber, this.sessionKey);
            }
            response = this.SendAndExpectSmbPacket(request, internalTimeout, out status);

            if (status != 0)
            {
                throw new InvalidOperationException("Tree Connect Failed. ErrorCode: " + status);
            }
            this.treeId = (response as SmbTreeConnectAndxResponsePacket).SmbHeader.Tid;
        }