API in C Sharp

From MikroTik Wiki
Revision as of 12:27, 19 May 2020 by Marisb (talk | contribs) (Class)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

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