API in C Sharp

From MikroTik Wiki
Revision as of 09:27, 19 May 2020 by Marisb (talk | contribs) (→‎Class)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

This is C# class for connecting and working with v3.x API

Class


class MK
    {   
        Stream connection;
        TcpClient con;

        public MK(string ip)
        {
            con = new TcpClient();
            con.Connect(ip, 8728);
            connection = (Stream)con.GetStream();
        }
        public void Close()
        {
            connection.Close();
            con.Close();
        }
        public bool Login(string username, string password)
        {
            Send("/login", true);
            string hash = Read()[0].Split(new string[] { "ret=" }, StringSplitOptions.None)[1];
            Send("/login");
            Send("=name=" + username);
            Send("=response=00" + EncodePassword(password, hash), true);
            if (Read()[0] == "!done")
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public void Send(string co)
        {
            Send(co, false);
        }
        public void Send(string co, bool endsentence)
        {
            byte[] bajty = Encoding.ASCII.GetBytes(co.ToCharArray());
            byte[] velikost = EncodeLength(bajty.Length);
            connection.Write(velikost, 0, velikost.Length);
            connection.Write(bajty, 0, bajty.Length);
            if (endsentence)
            {
                connection.WriteByte(0);
            }
        }
        public List<string> Read()
        {
            List<string> output = new List<string>();
            string o = "";
            byte[] tmp = new byte[4];
            long count;
            while (true)
            {
                tmp[3] = (byte)connection.ReadByte();
                //if(tmp[3] == 220) tmp[3] = (byte)connection.ReadByte(); it sometimes happend to me that 
                //mikrotik send 220 as some kind of "bonus" between words, this fixed things, not sure about it though
                if (tmp[3] == 0)
                {
                    output.Add(o);
                    if (o.Substring(0, 5) == "!done")
                    {
                        break;
                    }
                    else
                    {
                        o = "";
                        continue;
                    }
                }
                else
                {
                    if (tmp[3] < 0x80)
                    {
                        count = tmp[3];
                    }
                    else
                    {
                        if (tmp[3] < 0xC0)
                        {
                            int tmpi = BitConverter.ToInt32(new byte[] { (byte)connection.ReadByte(), tmp[3],0,0 }, 0);
                            count = tmpi ^ 0x8000;
                        }
                        else
                        {
                            if (tmp[3] < 0xE0)
                            {
                                tmp[2] = (byte)connection.ReadByte();
                                int tmpi = BitConverter.ToInt32(new byte[] { (byte)connection.ReadByte(), tmp[2], tmp[3],0 }, 0);
                                count = tmpi ^ 0xC00000;
                            }
                            else
                            {
                                if (tmp[3] < 0xF0)
                                {
                                    tmp[2] = (byte)connection.ReadByte();
                                    tmp[1] = (byte)connection.ReadByte();
                                    int tmpi = BitConverter.ToInt32(new byte[] { (byte)connection.ReadByte(), tmp[1], tmp[2], tmp[3] }, 0);
                                    count = tmpi ^ 0xE0000000;
                                }
                                else
                                {
                                    if (tmp[3] == 0xF0)
                                    {
                                        tmp[3] = (byte)connection.ReadByte();
                                        tmp[2] = (byte)connection.ReadByte();
                                        tmp[1] = (byte)connection.ReadByte();
                                        tmp[0] = (byte)connection.ReadByte();
                                        count = BitConverter.ToInt32(tmp, 0);
                                    }
                                    else
                                    {
                                        //Error in packet reception, unknown length
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }

                for (int i = 0; i < count; i++)
                {
                    o += (Char)connection.ReadByte();
                }
            }
            return output;
        }
        byte[] EncodeLength(int delka)
        {
            if (delka < 0x80)
            {
                byte[] tmp = BitConverter.GetBytes(delka);
                return new byte[1] { tmp[0] };
            }
            if (delka < 0x4000)
            {
                byte[] tmp = BitConverter.GetBytes(delka | 0x8000);
                return new byte[2] { tmp[1], tmp[0] };
            }
            if (delka < 0x200000)
            {
                byte[] tmp = BitConverter.GetBytes(delka | 0xC00000);
                return new byte[3] { tmp[2], tmp[1], tmp[0] };
            }
            if (delka < 0x10000000)
            {
                byte[] tmp = BitConverter.GetBytes(delka | 0xE0000000);
                return new byte[4] { tmp[3], tmp[2], tmp[1], tmp[0] };
            }
            else
            {
                byte[] tmp = BitConverter.GetBytes(delka);
                return new byte[5] { 0xF0, tmp[3], tmp[2], tmp[1], tmp[0] };
            }
        }

        public string EncodePassword(string Password, string hash)
        {
            byte[] hash_byte = new byte[hash.Length / 2];
            for (int i = 0; i <= hash.Length - 2; i += 2)
            {
                hash_byte[i / 2] = Byte.Parse(hash.Substring(i, 2), System.Globalization.NumberStyles.HexNumber);
            }
            byte[] heslo = new byte[1 + Password.Length + hash_byte.Length];
            heslo[0] = 0;
            Encoding.ASCII.GetBytes(Password.ToCharArray()).CopyTo(heslo, 1);
            hash_byte.CopyTo(heslo, 1 + Password.Length);

            Byte[] hotovo;
            System.Security.Cryptography.MD5 md5;

            md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();

            hotovo = md5.ComputeHash(heslo);

            //Convert encoded bytes back to a 'readable' string
            string navrat = "";
            foreach (byte h in hotovo)
            {
                navrat += h.ToString("x2");
            }
            return navrat;
        }
    }

Class with SSL support


using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Web;
using System.Web.UI.WebControls.WebParts;

namespace BitWorker.Classes
{
    public class MikrotikAPI
    {
        string _IPAddress;
        int _APIPort;
        bool _UseSSL;
        Stream _Stream;
        SslStream _SslStream;
        TcpClient _TcpClient;

        public MikrotikAPI(string IPAddress,bool UseSSL = false, int APIPort = 8728)
        {
            _IPAddress = IPAddress;
            _APIPort = APIPort;            
            _UseSSL = UseSSL;
        }

        public static bool ValidateServerCertificate(
              object sender,
              X509Certificate certificate,
              X509Chain chain,
              SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }

        public void Connect()
        {
            if (_UseSSL && _APIPort == 8728) _APIPort = 8729;

            _TcpClient = new TcpClient();
            _TcpClient.Connect(_IPAddress, _APIPort);

            if (_UseSSL)
            {
                _SslStream = new SslStream(_TcpClient.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
                _SslStream.AuthenticateAsClient(_IPAddress);
            }
            else
                _Stream = (Stream)_TcpClient.GetStream();
        }
        public void Disconnect()
        {
            if (_UseSSL)
                _Stream.Close();
            else
                _SslStream.Close();

            _TcpClient.Close();
        }

        public bool LoginDeprecated(string Username, string Password)
        {
            Send("/login", true);
            string hash = Receive()[0].Split(new string[] { "ret=" }, StringSplitOptions.None)[1];
            Send("/login");
            Send("=name=" + Username);
            Send("=response=00" + EncodePassword(Password, hash), true);
            List<string> ReceiveResult = Receive();
            if (ReceiveResult[0] == "!done")
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public bool Login(string Username, string Password, out string OutMessageDesc)
        {
            OutMessageDesc = "";

            Send("/login");
            Send("=name=" + Username);
            Send("=password=" + Password, true);
            List<string> ReceiveResult = Receive();
            if (ReceiveResult[0] == "!done")
            {
                return true;
            }
            else
            {
                OutMessageDesc = ReceiveResult[1];
                return false;
            }
        }

        public void Send(string DataToSend, bool EndofPacket = false)
        {
            if (_UseSSL)
                DoSendSSL(DataToSend, EndofPacket);
            else
                DoSend(DataToSend, EndofPacket);
        }

        private void DoSend(string DataToSend, bool EndofPacket = false)
        {
            byte[] DataToSendasByte = Encoding.ASCII.GetBytes(DataToSend.ToCharArray());
            byte[] SendSize = EncodeLength(DataToSendasByte.Length);
            _Stream.Write(SendSize, 0, SendSize.Length);
            _Stream.Write(DataToSendasByte, 0, DataToSendasByte.Length);
            if (EndofPacket) _Stream.WriteByte(0);
        }

        private void DoSendSSL(string DataToSend, bool EndofPacket = false)
        {
            byte[] DataToSendasByte = Encoding.ASCII.GetBytes(DataToSend.ToCharArray());
            byte[] SendSize = EncodeLength(DataToSendasByte.Length);
            _SslStream.Write(SendSize, 0, SendSize.Length);
            _SslStream.Write(DataToSendasByte, 0, DataToSendasByte.Length);
            if (EndofPacket) _SslStream.WriteByte(0);
        }

        public ArrayList ReceiveList()
        {
            List<string> ReceivedDataList;

            if (_UseSSL)
                ReceivedDataList = DoReceiveSSL();
            else
                ReceivedDataList = DoReceive();

            ArrayList DataList = new ArrayList();
            List<string> ReceivedData = new List<string>();
            foreach (string DataLine in ReceivedDataList)
            {
                if (DataLine == "!re" || DataLine == "!done" || DataLine == "!trap")
                {
                    DataList.Add(ReceivedData);
                    ReceivedData = new List<string>();
                }
                else
                    ReceivedData.Add(DataLine);
            }
            if (DataList.Count > 1) DataList.RemoveAt(0);

            return DataList;
        }


        public List<string> Receive()
        {
            if (_UseSSL)
                return DoReceiveSSL();
            else
                return DoReceive();
        }

        private List<string> DoReceive()
        {
            List<string> OutputList = new List<string>();
            long TempReceiveSize;
            string TempString = "";
            long ReceiveSize = 0;
            while (true)
            {
                TempReceiveSize = (byte)_Stream.ReadByte();
                if (TempReceiveSize > 0)
                {
                    if ((TempReceiveSize & 0x80) == 0)
                    {
                        ReceiveSize = TempReceiveSize;
                    }
                    else if ((TempReceiveSize & 0xC0) == 0x80)
                    {
                        TempReceiveSize &= ~0xC0;
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_Stream.ReadByte();
                        ReceiveSize = TempReceiveSize;
                    }
                    else if ((TempReceiveSize & 0xE0) == 0xC0)
                    {
                        TempReceiveSize &= ~0xE0;
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_Stream.ReadByte();
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_Stream.ReadByte();
                        ReceiveSize = TempReceiveSize;
                    }
                    else if ((TempReceiveSize & 0xF0) == 0xE0)
                    {
                        TempReceiveSize &= ~0xF0;
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_Stream.ReadByte();
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_Stream.ReadByte();
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_Stream.ReadByte();
                        ReceiveSize = TempReceiveSize;
                    }
                    else if ((TempReceiveSize & 0xF8) == 0xF0)
                    {
                        TempReceiveSize += (byte)_Stream.ReadByte();
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_Stream.ReadByte();
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_Stream.ReadByte();
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_Stream.ReadByte();
                        ReceiveSize = TempReceiveSize;
                    }
                }
                else
                    ReceiveSize = TempReceiveSize;

                for (int i = 0; i < ReceiveSize; i++)
                {
                    Char TempChar = (Char)_Stream.ReadByte();
                    TempString += TempChar;
                }

                if (ReceiveSize > 0)
                {
                    OutputList.Add(TempString);
                    if (TempString == "!done") break;
                    TempString = "";
                }
            }
            return OutputList;
        }

        private List<string> DoReceiveSSL()
        {
            List<string> OutputList = new List<string>();
            long TempReceiveSize;
            string TempString = "";
            long ReceiveSize = 0;
            while (true)
            {
                TempReceiveSize = (byte)_SslStream.ReadByte();
                if (TempReceiveSize > 0)
                {
                    if ((TempReceiveSize & 0x80) == 0)
                    {
                        ReceiveSize = TempReceiveSize;
                    }
                    else if ((TempReceiveSize & 0xC0) == 0x80)
                    {
                        TempReceiveSize &= ~0xC0;
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_SslStream.ReadByte();
                        ReceiveSize = TempReceiveSize;
                    }
                    else if ((TempReceiveSize & 0xE0) == 0xC0)
                    {
                        TempReceiveSize &= ~0xE0;
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_SslStream.ReadByte();
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_SslStream.ReadByte();
                        ReceiveSize = TempReceiveSize;
                    }
                    else if ((TempReceiveSize & 0xF0) == 0xE0)
                    {
                        TempReceiveSize &= ~0xF0;
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_SslStream.ReadByte();
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_SslStream.ReadByte();
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_SslStream.ReadByte();
                        ReceiveSize = TempReceiveSize;
                    }
                    else if ((TempReceiveSize & 0xF8) == 0xF0)
                    {
                        TempReceiveSize += (byte)_SslStream.ReadByte();
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_SslStream.ReadByte();
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_SslStream.ReadByte();
                        TempReceiveSize <<= 8;
                        TempReceiveSize += (byte)_SslStream.ReadByte();
                        ReceiveSize = TempReceiveSize;
                    }
                }
                else
                    ReceiveSize = TempReceiveSize;

                for (int i = 0; i < ReceiveSize; i++)
                {
                    Char TempChar = (Char)_SslStream.ReadByte();
                    TempString += TempChar;
                }

                if (ReceiveSize > 0)
                {
                    OutputList.Add(TempString);
                    if (TempString == "!done") break;
                    TempString = "";
                }
            }
            return OutputList;
        }

        private byte[] EncodeLength(int delka)
        {
            if (delka < 0x80)
            {
                byte[] tmp = BitConverter.GetBytes(delka);
                return new byte[1] { tmp[0] };
            }
            if (delka < 0x4000)
            {
                byte[] tmp = BitConverter.GetBytes(delka | 0x8000);
                return new byte[2] { tmp[1], tmp[0] };
            }
            if (delka < 0x200000)
            {
                byte[] tmp = BitConverter.GetBytes(delka | 0xC00000);
                return new byte[3] { tmp[2], tmp[1], tmp[0] };
            }
            if (delka < 0x10000000)
            {
                byte[] tmp = BitConverter.GetBytes(delka | 0xE0000000);
                return new byte[4] { tmp[3], tmp[2], tmp[1], tmp[0] };
            }
            else
            {
                byte[] tmp = BitConverter.GetBytes(delka);
                return new byte[5] { 0xF0, tmp[3], tmp[2], tmp[1], tmp[0] };
            }
        }

        private string EncodePassword(string Password, string hash)
        {
            byte[] hash_byte = new byte[hash.Length / 2];
            for (int i = 0; i <= hash.Length - 2; i += 2)
            {
                hash_byte[i / 2] = Byte.Parse(hash.Substring(i, 2), System.Globalization.NumberStyles.HexNumber);
            }
            byte[] heslo = new byte[1 + Password.Length + hash_byte.Length];
            heslo[0] = 0;
            Encoding.ASCII.GetBytes(Password.ToCharArray()).CopyTo(heslo, 1);
            hash_byte.CopyTo(heslo, 1 + Password.Length);

            Byte[] hotovo;
            System.Security.Cryptography.MD5 md5;

            md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();

            hotovo = md5.ComputeHash(heslo);

            //Convert encoded bytes back to a 'readable' string
            string navrat = "";
            foreach (byte h in hotovo)
            {
                navrat += h.ToString("x2");
            }
            return navrat;
        }

    }
}

Example


using System.IO;
using System.Net.Sockets;


class Program
    {
        static void Main(string[] args)
        {

            MK mikrotik = new MK("your ip here");
            if (!mikrotik.Login("username", "password"))
            {
                Console.WriteLine("Could not log in");
                mikrotik.Close();
                return;
            }
            mikrotik.Send("/system/identity/getall");
            mikrotik.Send(".tag=sss", true);
            foreach (string h in mikrotik.Read())
            {
                Console.WriteLine(h);
            }
            Console.ReadKey();
        }
    }

Example 2

Block SMTP port and specific Ip rule by Oguzhan


using System.IO;
using System.Net.Sockets;

    class Program
    {
        static void Main(string[] args)
        {
            string ip = args[0];
            MK mikrotik = new MK("your ip here");
            if (mikrotik.Login("admin", "P@ssW0rd"))
            {
                mikrotik.Send("/ip/firewall/filter/add");
                mikrotik.Send("=action=drop");
                mikrotik.Send("=chain=forward");
                mikrotik.Send("=dst-port=25");
                mikrotik.Send("=protocol=tcp");
                mikrotik.Send("=protocol=tcp");
                mikrotik.Send(String.Format("=src-address={0}",ip));

                mikrotik.Send(".tag=firewall", true);

                foreach (string h in mikrotik.Read())
                {
                    Console.WriteLine(h);
                }
            }
        }
    }


Notes

  • I have not tested it thorougly (especialy length encoding with longer words)
  • You have to have using System.IO; and using System.Net.Sockets;
  • Exceptions are not handled

See also