/// <summary>Receives data from an open stream.</summary>
        /// <returns>Retrieved data</returns>
        public byte[] Read()
        {
            byte[] responseLength = new byte[4];

            using (BigEndianMemoryStream readStream = new BigEndianMemoryStream())
            {
                if (!this.bufferedStream.CanRead)
                {
                    return(null);
                }

                this.bufferedStream.Read(responseLength, 0, 4);
                readStream.Write(responseLength, 0, 4);
                Debug.WriteLine("Packet length: " + BitConverter.ToString(responseLength));
                long bytesToRead = Converters.BigEndianToUInt32(responseLength);
                if (bytesToRead == 0x00000000 || bytesToRead == 0x40404040)
                {
                    return(null);
                }

                bytesToRead -= 4;
                while (bytesToRead > 0)
                {
                    byte[] buffer = new byte[(long)byte.MaxValue < bytesToRead ? byte.MaxValue : (int)bytesToRead];
                    if (!this.bufferedStream.CanRead)
                    {
                        Thread.Sleep(100);
                    }
                    this.bufferedStream.Read(buffer, 0, buffer.Length);
                    readStream.Write(buffer, 0, buffer.Length);
                    bytesToRead -= buffer.Length;
                }
                return(readStream.ToArray());
            }
        }
예제 #2
0
        //-----------------------------------------------------------------------
        // Private methods
        //-----------------------------------------------------------------------

        /// <summary>Connects to the Sign-on Verify server</summary>
        private void ConnectToSignonVerifyServer()
        {
            // Establish authentication channel
            this.socketConnectorSignonVerify = new SocketConnector(this.serverName, this.useSSL ? TcpPortSignonVerifySSL : TcpPortSignonVerify, this.useSSL, this.ignoreSelfSignedCertificates);

            // Default current seed information
            this.clientSeed = 0;
            this.serverSeed = 0;

            // Exchange random seeds
            ulong clientSeed = (ulong)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
            BigEndianMemoryStream outputStream = new BigEndianMemoryStream();

            ////           outputStream.WriteInt(52); // length
            outputStream.WriteShort(0);                    // Header ID (0)
            outputStream.WriteShort(ServerIDSignonVerify); // Server ID
            outputStream.WriteInt(0);                      // CS instance
            outputStream.WriteInt(0);                      // Correlation ID
            outputStream.WriteShort(0);                    // Template length
            outputStream.WriteShort(0x7003);               // ReqReP ID
            outputStream.WriteInt(10);                     // Client version LL
            outputStream.WriteShort(0x1101);               // Client version CP
            outputStream.WriteInt(1);                      // Client version
            outputStream.WriteInt(8);                      // Client data stream level LL
            outputStream.WriteShort(0x1102);               // Client datastream level CP
            outputStream.WriteShort(2);                    // Client datastream level
            outputStream.WriteInt(14);                     // Client seed LL
            outputStream.WriteShort(0x1103);               // Client seed CP
            outputStream.WriteLong(clientSeed);            // Client seed
            this.socketConnectorSignonVerify.Write(outputStream.ToArray());

            // Retrieve server response
            byte[] response = this.socketConnectorSignonVerify.Read();
            BigEndianMemoryStream inputStream = new BigEndianMemoryStream();

            inputStream.Write(response, 0, response.Length);

            /*
             *  The response comes  in the following format:
             *
             *  Offset (byte)       Information         Length (byte)
             *  -----------------------------------------------------------
             *  Fixed header
             *  -----------------------------------------------------------
             *  0                   Response length     4
             *  4                   (Reserved)          16
             *  20                  Result code         4
             *  24                  (Dynamic fields)    see below
             *  -----------------------------------------------------------
             *  Dynamic fields (Offset is dynamic)
             *  -----------------------------------------------------------
             *  0                   Field length        4
             *  4                   Field code          2
             *  6                   Field data          (Field length - 6)
             */

            // Read fixed header
            inputStream.Position = 0;
            uint responseLength = inputStream.ReadInt();

            if (responseLength < 20)
            {
                throw new System.InvalidOperationException("Seeds exchange failed. Bad response length.");
            }

            inputStream.Position += 16;

            uint resultCode = inputStream.ReadInt();

            if (resultCode != 0)
            {
                throw new System.InvalidOperationException("Seeds exchange failed. Bad return code.");
            }

            while (inputStream.Position < responseLength)
            {
                uint   dynamicFieldLength = inputStream.ReadInt();
                ushort dynamicFieldCode   = inputStream.ReadShort();
                byte[] dynamicFieldData   = new byte[dynamicFieldLength - 6];
                inputStream.Read(dynamicFieldData, 0, (int)dynamicFieldLength - 6);

                switch (dynamicFieldCode)
                {
                case 0x1101:        // Server Version
                    this.serverVersion = Converters.BigEndianToUInt32(dynamicFieldData);
                    break;

                case 0x1102:        // Server Level
                    this.serverLevel = Converters.BigEndianToUInt16(dynamicFieldData);
                    break;

                case 0x1103:        // Server Seed
                    this.serverSeed = Converters.BigEndianToUInt64(dynamicFieldData);
                    break;

                case 0x1119:        // Password Level
                    this.passwordLevel = Converters.BigEndianToUInt8(dynamicFieldData);
                    break;

                case 0x111F:        // Job Name
                    this.jobName = Converters.EbcdicToAsciiString(dynamicFieldData, 4);
                    break;

                default:
                    break;
                }
            }

            Debug.WriteLine("Seeds were exchanged, return code is 0x" + resultCode.ToString("X8"));

            this.clientSeed = clientSeed;
        }
예제 #3
0
        /// <summary>Authenticates the user to the remote command server</summary>
        private void AuthenticateToRemoteCommandServer()
        {
            // Establish command channel
            if (this.socketConnectorRemoteCommand == null)
            {
                throw new System.InvalidOperationException("Operation failed, connection not established.");
            }

            BigEndianMemoryStream outputStream = new BigEndianMemoryStream();

            byte[] encryptedPassword;
            byte[] userID = Converters.AsciiToEbcdic(this.userName.ToUpper().PadRight(10));
            encryptedPassword = this.passwordLevel < 2 ? Encryption.EncryptPasswordDES(this.userName, this.password, this.serverSeed, this.clientSeed) : Encryption.EncryptPasswordSHA1(this.userName, this.password, this.serverSeed, this.clientSeed);

            outputStream.WriteByte(2);                                          // Client attributes (2: return job information)
            outputStream.WriteByte(0);                                          // Server attributes
            outputStream.WriteShort(ServerIDRemoteCommand);                     // Server ID
            outputStream.WriteInt(0);                                           // CS instance
            outputStream.WriteInt(0);                                           // Correlation ID
            outputStream.WriteShort(2);                                         // Template length
            outputStream.WriteShort(0x7002);                                    // ReqReP ID
            outputStream.WriteByte((byte)(this.passwordLevel < 2 ? 1 : 3));     // Password encryption type
            outputStream.WriteByte(1);                                          // Send reply
            outputStream.WriteInt(6 + (uint)encryptedPassword.Length);          // Password LL
            outputStream.WriteShort(0x1105);                                    // Password CP. 0x1115 is other.
            outputStream.Write(encryptedPassword, 0, encryptedPassword.Length); // Password
            outputStream.WriteInt(16);                                          // User ID LL
            outputStream.WriteShort(0x1104);                                    // User ID CP
            outputStream.Write(userID, 0, userID.Length);                       // UserID

            this.socketConnectorRemoteCommand.Write(outputStream.ToArray());

            // Retrieve server response
            byte[] response = this.socketConnectorRemoteCommand.Read();
            BigEndianMemoryStream inputStream = new BigEndianMemoryStream();

            inputStream.Write(response, 0, response.Length);

            /*
             *  The response comes  in the following format:
             *
             *  Offset (byte)       Information         Length (byte)
             *  -----------------------------------------------------------
             *  Fixed header
             *  -----------------------------------------------------------
             *  0                   Response length     4
             *  4                   (Reserved)          16
             *  20                  Result code         4
             *  24                  (Dynamic fields)    see below
             *  -----------------------------------------------------------
             *  Dynamic fields (Offset is dynamic)
             *  -----------------------------------------------------------
             *  0                   Field length        4
             *  4                   Field code          2
             *  6                   Field data          (Field length - 6)
             */

            // Read fixed header
            inputStream.Position = 0;
            uint responseLength = inputStream.ReadInt();

            if (responseLength < 20)
            {
                throw new System.InvalidOperationException("Authentication failed. Bad response length.");
            }

            inputStream.Position += 16;

            uint resultCode = inputStream.ReadInt();

            if (resultCode != 0)
            {
                if ((resultCode & 0xFFFF0000) == 0x00010000)
                {
                    throw new System.InvalidOperationException("Authentication failed. Error on request data.");
                }
                if ((resultCode & 0xFFFF0000) == 0x00040000)
                {
                    throw new System.InvalidOperationException("Authentication failed. General security error, function not performed.");
                }
                if ((resultCode & 0xFFFF0000) == 0x00060000)
                {
                    throw new System.InvalidOperationException("Authentication failed. Authentication token error.");
                }
                switch (resultCode)
                {
                case 0x00020001:
                    throw new System.InvalidOperationException("Authentication failed. User ID unknown.");

                case 0x00020002:
                    throw new System.InvalidOperationException("Authentication failed. User ID locked.");

                case 0x00020003:
                    throw new System.InvalidOperationException("Authentication failed. User ID doesn't match the authentication token.");

                case 0x0003000B:
                    throw new System.InvalidOperationException("Authentication failed. Password incorrect.");

                case 0x0003000C:
                    throw new System.InvalidOperationException("Authentication failed. Password incorrect. User profile will be revoked on next invalid password or passphrase.");

                case 0x0003000D:
                    throw new System.InvalidOperationException("Authentication failed. Password is expired.");

                case 0x0003000E:
                    throw new System.InvalidOperationException("Authentication failed. Pre-V2R2 encrypted password.");

                case 0x00030010:
                    throw new System.InvalidOperationException("Authentication failed. Password is *NONE.");

                default:
                    throw new System.InvalidOperationException("Authentication failed. Return code 0x" + resultCode.ToString("X8"));
                }
            }

            while (inputStream.Position < responseLength)
            {
                uint   dynamicFieldLength = inputStream.ReadInt();
                ushort dynamicFieldCode   = inputStream.ReadShort();
                byte[] dynamicFieldData   = new byte[dynamicFieldLength - 6];
                inputStream.Read(dynamicFieldData, 0, (int)dynamicFieldLength - 6);

                switch (dynamicFieldCode)
                {
                case 0x111F:        // Server Version
                    this.jobName = Converters.EbcdicToAsciiString(dynamicFieldData, 4);
                    break;

                default:
                    break;
                }
            }

            Debug.WriteLine("User authenticated to remote command server.");
        }
예제 #4
0
        /// <summary>Authenticates the user to the signon server</summary>
        private void AuthenticateToSignonVerifyServer()
        {
            BigEndianMemoryStream outputStream = new BigEndianMemoryStream();

            byte[] encryptedPassword;
            byte[] userID = Converters.AsciiToEbcdic(this.userName.ToUpper().PadRight(10));
            encryptedPassword = this.passwordLevel < 2 ? Encryption.EncryptPasswordDES(this.userName, this.password, this.serverSeed, this.clientSeed) : Encryption.EncryptPasswordSHA1(this.userName, this.password, this.serverSeed, this.clientSeed);

            if (this.serverLevel >= 5)
            {
                outputStream.WriteShort(0);                                     // Header ID (0)
            }
            outputStream.WriteShort(ServerIDSignonVerify);                      // Server ID
            outputStream.WriteInt(0);                                           // CS instance
            outputStream.WriteInt(0);                                           // Correlation ID
            outputStream.WriteShort(0x0001);                                    // Template length
            outputStream.WriteShort(0x7004);                                    // ReqReP ID
            outputStream.WriteByte((byte)(this.passwordLevel < 2 ? 1 : 3));     // Password encryption type
            outputStream.WriteInt(10);                                          // Client CCSID LL
            outputStream.WriteShort(0x1113);                                    // Client CCSID CP
            outputStream.WriteInt(1200);                                        // Client CCSID (big endian UTF-16)
            outputStream.WriteInt(6 + (uint)encryptedPassword.Length);          // Password LL
            outputStream.WriteShort(0x1105);                                    // Password CP. 0x1115 is other.
            outputStream.Write(encryptedPassword, 0, encryptedPassword.Length); // Password
            outputStream.WriteInt(16);                                          // User ID LL
            outputStream.WriteShort(0x1104);                                    // User ID CP
            outputStream.Write(userID, 0, userID.Length);                       // UserID
            if (this.serverLevel >= 5)
            {
                outputStream.WriteInt(7);        // Return error messages LL
                outputStream.WriteShort(0x1128); // Return error messages CP
                outputStream.WriteByte(1);       // Return error messages
            }

            this.socketConnectorSignonVerify.Write(outputStream.ToArray());

            // Retrieve server response
            byte[] response = this.socketConnectorSignonVerify.Read();
            BigEndianMemoryStream inputStream = new BigEndianMemoryStream();

            inputStream.Write(response, 0, response.Length);

            /*
             *  The response comes  in the following format:
             *
             *  Offset (byte)       Information         Length (byte)
             *  -----------------------------------------------------------
             *  Fixed header
             *  -----------------------------------------------------------
             *  0                   Response length     4
             *  4                   (Reserved)          16
             *  20                  Result code         4
             *  24                  (Dynamic fields)    see below
             *  -----------------------------------------------------------
             *  Dynamic fields (Offset is dynamic)
             *  -----------------------------------------------------------
             *  0                   Field length        4
             *  4                   Field code          2
             *  6                   Field data          (Field length - 6)
             */

            // Read fixed header
            inputStream.Position = 0;
            uint responseLength = inputStream.ReadInt();

            if (responseLength < 20)
            {
                throw new System.InvalidOperationException("Authentication failed. Bad response length.");
            }

            inputStream.Position += 16;

            uint resultCode = inputStream.ReadInt();

            if (resultCode != 0)
            {
                switch (resultCode)
                {
                case 0x00020001:
                    throw new System.InvalidOperationException("Authentication failed. Unknown username.");

                case 0x0003000B:
                    throw new System.InvalidOperationException("Authentication failed. Wrong password.");

                case 0x0003000C:
                    throw new System.InvalidOperationException("Authentication failed. Wrong password. Profile will be disabled on the next invalid password.");

                case 0x0003000D:
                    throw new System.InvalidOperationException("Authentication failed. Password is expired.");

                case 0x00030010:
                    throw new System.InvalidOperationException("Authentication failed. Password is *NONE.");

                default:
                    throw new System.InvalidOperationException("Authentication failed. Return code 0x" + resultCode.ToString("X8"));
                }
            }

            while (inputStream.Position < responseLength)
            {
                uint   dynamicFieldLength = inputStream.ReadInt();
                ushort dynamicFieldCode   = inputStream.ReadShort();
                byte[] dynamicFieldData   = new byte[dynamicFieldLength - 6];
                inputStream.Read(dynamicFieldData, 0, (int)dynamicFieldLength - 6);

                switch (dynamicFieldCode)
                {
                case 0x1114:        // Server Version
                    this.serverCCSID = Converters.BigEndianToUInt32(dynamicFieldData);
                    break;

                default:
                    break;
                }
            }

            Debug.WriteLine("User authenticated to signon server.");
        }
예제 #5
0
        /// <summary>Retrieves server information</summary>
        private void RetrieveRemoteCommandServerInformation()
        {
            // Establish command channel
            if (this.socketConnectorRemoteCommand == null)
            {
                throw new System.InvalidOperationException("Operation failed, connection not established.");
            }

            BigEndianMemoryStream outputStream = new BigEndianMemoryStream();

            outputStream.WriteShort(0);                                 // Header ID
            outputStream.WriteShort(ServerIDRemoteCommand);             // Server ID
            outputStream.WriteInt(0);                                   // CS instance
            outputStream.WriteInt(0);                                   // Correlation ID
            outputStream.WriteShort(14);                                // Template length
            outputStream.WriteShort(0x1001);                            // ReqReP ID
            outputStream.WriteInt(1200);                                // Operation is CCSID
            outputStream.Write(Converters.AsciiToEbcdic("2924"), 0, 4); // NLV value (default = 2924 = English)
            outputStream.WriteInt(1);                                   // Client version
            outputStream.WriteShort(0);                                 // Client datastream level
            this.socketConnectorRemoteCommand.Write(outputStream.ToArray());

            // Retrieve server response
            byte[] response = this.socketConnectorRemoteCommand.Read();
            BigEndianMemoryStream inputStream = new BigEndianMemoryStream();

            inputStream.Write(response, 0, response.Length);

            /*
             *  The response comes  in the following format:
             *
             *  Offset (byte)       Information         Length (byte)
             *  -----------------------------------------------------------
             *  Fixed header
             *  -----------------------------------------------------------
             *  0                   Response length     4
             *  4                   (Reserved)          16
             *  20                  Result code         2
             *  24                  CCSID               4
             *  28                  NLV (in EBCDIC)     4
             *  32                  (reserved)          4
             *  36                  Datastream level    2
             */

            // Read fixed header
            inputStream.Position = 0;
            uint responseLength = inputStream.ReadInt();

            if (responseLength < 20)
            {
                throw new System.InvalidOperationException("Seeds exchange failed. Bad response length.");
            }

            inputStream.Position += 16;

            uint resultCode = inputStream.ReadShort();

            // We ignore the same return codes that JTOPEN/JT400 ignores
            if (resultCode != 0x0100 &&  // User with *LMTCPB = *YES
                resultCode != 0x0104 &&  // Invalid CCSID.
                resultCode != 0x0105 &&  // Invalid NLV, default to primary NLV:
                resultCode != 0x0106 &&  // NLV not installed, default to primary NLV:
                                         // The NLV may not be supported or it may not be installed on the system.
                resultCode != 0x0107 &&  // Error retrieving product information.  Can't validate NLV.
                resultCode != 0x0108 &&  // Error trying to add NLV library to system library list:
                                         // One possible reason for failure is the user may not be authorized to CHGSYSLIBL command.
                resultCode != 0)
            {
                throw new System.InvalidOperationException("Invalid operation, failed to retrieve Remote Command server attributes.");
            }

            this.serverCCSID = inputStream.ReadInt();
            byte[] nlv = new byte[4];
            inputStream.Read(nlv, 0, 4);
            this.serverNLV             = Converters.EbcdicToAsciiString(nlv);
            inputStream.Position      += 4;
            this.serverDatastreamLevel = inputStream.ReadShort();

            Debug.WriteLine("Remote Command server attributes retrieved, return code is 0x" + resultCode.ToString("X8"));
        }
예제 #6
0
        /// <summary>Connects to the Remote Command server</summary>
        private void ConnectToRemoteCommandServer()
        {
            // Establish command channel
            this.socketConnectorRemoteCommand = new SocketConnector(this.serverName, this.useSSL ? TcpPortRemoteCommandSSL : TcpPortRemoteCommand, this.useSSL, this.ignoreSelfSignedCertificates);

            // Default current seed information
            this.clientSeed = 0;
            this.serverSeed = 0;

            // Exchange random seeds
            ulong clientSeed = (ulong)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
            BigEndianMemoryStream outputStream = new BigEndianMemoryStream();

            outputStream.WriteByte(1);                      // Client attributes (1 = SHA-1 capability enabled)
            outputStream.WriteByte(0);                      // Server attributes
            outputStream.WriteShort(ServerIDRemoteCommand); // Server ID
            outputStream.WriteInt(0);                       // CS instance
            outputStream.WriteInt(0);                       // Correlation ID
            outputStream.WriteShort(8);                     // Template length
            outputStream.WriteShort(0x7001);                // ReqReP ID
            outputStream.WriteLong(clientSeed);             // Client seed
            this.socketConnectorRemoteCommand.Write(outputStream.ToArray());

            // Retrieve server response
            byte[] response = this.socketConnectorRemoteCommand.Read();
            BigEndianMemoryStream inputStream = new BigEndianMemoryStream();

            inputStream.Write(response, 0, response.Length);

            /*
             *  The response comes  in the following format:
             *
             *  Offset (byte)       Information         Length (byte)
             *  -----------------------------------------------------------
             *  Fixed header
             *  -----------------------------------------------------------
             *  0                   Response length     4
             *  4                   (Reserved)          16
             *  20                  Result code         4
             *  24                  Server seed         8
             */

            // Read fixed header
            inputStream.Position = 0;
            uint responseLength = inputStream.ReadInt();

            if (responseLength < 20)
            {
                throw new System.InvalidOperationException("Seeds exchange failed. Bad response length.");
            }

            inputStream.Position += 16;

            uint resultCode = inputStream.ReadInt();

            if (resultCode != 0)
            {
                throw new System.InvalidOperationException("Seeds exchange failed. Bad return code.");
            }

            this.serverSeed = inputStream.ReadLong();
            this.clientSeed = clientSeed;

            Debug.WriteLine("Seeds were exchanged, return code is 0x" + resultCode.ToString("X8"));
        }