Page 1 of 1

Mikrotik API and C# ?

Posted: Tue Dec 25, 2007 3:27 pm
by taz
Hi, any example for C-Sharp ?

thx

Re: Mikrotik API and C# ?

Posted: Thu Feb 07, 2008 10:02 am
by janisk
ok it is not C# but plain java example on how to get that API thing working

http://forum.mikrotik.com/viewtopic.php ... 07#p103407

Re: Mikrotik API and C# ?

Posted: Thu Feb 07, 2008 1:17 pm
by tgrand
Something thrown together in vb.net.
The only caveat is that if you optomize or enhance this code, please share on the wiki.

Public Class ApiRos
Dim thisSocket As System.Net.Sockets.Socket
Dim thisTag As Integer
Dim thisStream As System.Net.Sockets.NetworkStream
Dim attr(1024) As String, aval(1024) As String



Public Function hex2ascii(ByVal hextext As String) As Byte()
Dim y As Integer
Dim num As String
Dim bytes((hextext.Length - 2) / 2) As Byte
Dim value As String = ""
Dim i As Integer = 0
For y = 0 To hextext.Length - 2
num = Mid(hextext, y + 1, 2)
value = value & Chr(Val("&h" & num))
bytes(i) = Val("&h" & num)
y = y + 1
i = i + 1
Next y
Return bytes
End Function

Private Function StringToHex(ByVal password As String) As String
Dim retString As String = ""
Dim stringBytes() As Byte = System.Text.ASCIIEncoding.ASCII.GetBytes(password)
Dim i As Integer = 0
For i = 0 To stringBytes.Length - 1
Dim hexTmp As String = Hex(stringBytes(i))
If hexTmp.Length = 1 Then
retString = retString & "0" & hexTmp
Else
retString = retString & hexTmp
End If
Next
Return retString
End Function




Public Sub New(ByVal sk As System.Net.Sockets.Socket)
thisSocket = sk
thisTag = 0
thisStream = New System.Net.Sockets.NetworkStream(thisSocket, True)
End Sub

Public Sub login(ByVal username As String, ByVal pwd As String)
Dim i As Integer
Dim words(1) As String

Dim writebuffer(1024) As Byte
Dim readbuffer(1024) As Byte


words(0) = "/login"
talk(words, attr, aval)

Dim mymd5 As System.Security.Cryptography.MD5 = New System.Security.Cryptography.MD5CryptoServiceProvider
'writebuffer = hex2ascii("00" + aval(0) + StringToHex(pwd))
readbuffer.Initialize()
readbuffer = hex2ascii("00" + StringToHex(pwd) + aval(0))
writebuffer = mymd5.ComputeHash(readbuffer)

Dim retresp As String

retresp = "=response=00"
For i = 0 To writebuffer.Length - 1
retresp += Format(writebuffer(i), "X2")
Next

Debug.Print("**** " + retresp)

ReDim words(3)
words(0) = "/login"
words(1) = "=name=" + username
words(2) = retresp
talk(words, attr, aval)
End Sub

Public Sub talk(ByVal words() As String, ByRef attr() As String, ByRef aval() As String)
Dim i As String = ""
Dim r As String = ""

If writeSentence(words) = 0 Then
attr(0) = ""
aval(0) = ""
Exit Sub
End If

Dim attrcount As Integer = 0
Do While 1
i = readSentence()
If Len(i) = 0 Then
attr(attrcount) = ""
aval(attrcount) = ""
Exit Sub
End If

Dim ipos As Integer = InStr(1, i, "=", CompareMethod.Text)
Dim ipos2 As Integer = InStr(ipos + 1, i, "=", CompareMethod.Text)
If ((ipos = 0) Or (ipos > i.Length)) And i(0) = "!" Then ipos = 1
attr(attrcount) = Mid(i, ipos, ipos2 - ipos + 1)
aval(attrcount) = Mid(i, ipos2 + 1, Len(i) - ipos2)
attrcount += 1
Loop
End Sub

Public Function writeSentence(ByVal words() As String) As Integer
Dim ret As Integer = 0
Dim st As String

For Each st In words
If Not st Is Nothing Then
writeWord(st)
ret += 1
End If
Next

writeWord("")

Return ret
End Function

Public Function readSentence() As String
Dim r As String = ""
Dim w As String
Dim i As Integer = 0
Do While 1
w = readWord()
If w = "" Then Return r
r += Trim(w)
i += 1
Loop

Return r
End Function

Public Sub writeWord(ByVal w As String)
Debug.Print("<<< " + w)
writeLen(Len(w))
writeStr(w)
End Sub

Public Function readWord() As String
Dim readbuffer(4096) As Byte
Dim ret As String
Dim dsize As Integer

dsize = readLen()
ReDim readbuffer(dsize)
readbuffer = readStr(dsize)
ret = System.Text.Encoding.ASCII.GetString(readbuffer, 0, dsize)
Debug.Print(">>> " + ret)

Return Trim(ret)
End Function

Public Sub writeLen(ByVal l As Integer)
If l < &H80 Then
writeStr(Chr(l))
ElseIf l < &H4000 Then
l = l Or &H8000
writeStr(Chr((l >> 8 ) & &HFF))
writeStr(Chr(l & &HFF))
ElseIf l < &H200000 Then
l = l Or &HC00000
writeStr(Chr((l >> 16) & &HFF))
writeStr(Chr((l >> 8 ) & &HFF))
writeStr(Chr(l & &HFF))
ElseIf l < &H10000000 Then
l = l Or &HE0000000
writeStr(Chr((l >> 24) & &HFF))
writeStr(Chr((l >> 16) & &HFF))
writeStr(Chr((l >> 8 ) & &HFF))
writeStr(Chr(l & &HFF))
Else
writeStr(Chr(&HF0))
writeStr(Chr((l >> 24) & &HFF))
writeStr(Chr((l >> 16) & &HFF))
writeStr(Chr((l >> 8 ) & &HFF))
writeStr(Chr(l & &HFF))
End If
End Sub

Public Function readLen() As Integer
Dim cb As Byte() = readStr(1)

If cb.Length = 0 Then Return 0

Dim c As Integer = CInt(cb(0)) ') & &HFF

If (c And &H80) = &H0 Then
ElseIf (c And &HC0) = &H80 Then
c = c And (Not &HC0)
c <<= 8
c += Convert.ToInt32(readStr(1)) & &HFF
ElseIf (c And &HE0) = &HC0 Then
c = c And (Not &HE0)
c <<= 8
c += Convert.ToInt32(readStr(1)) & &HFF
c <<= 8
c += Convert.ToInt32(readStr(1)) & &HFF
ElseIf (c & &HF0) = &HE0 Then
c &= (Not &HF0)
c <<= 8
c += Convert.ToInt32(readStr(1)) & &HFF
c <<= 8
c += Convert.ToInt32(readStr(1)) & &HFF
c <<= 8
c += Convert.ToInt32(readStr(1)) & &HFF
ElseIf (c & &HF8 ) = &HF0 Then
c = Convert.ToInt32(readStr(1)) & &HFF
c <<= 8
c += Convert.ToInt32(readStr(1)) & &HFF
c <<= 8
c += Convert.ToInt32(readStr(1)) & &HFF
c <<= 8
c += Convert.ToInt32(readStr(1)) & &HFF
End If

Return c
End Function

Public Sub writeStr(ByVal str As String)
Dim writebuffer(Len(str)) As Byte

writebuffer = System.Text.Encoding.ASCII.GetBytes(str)
If writebuffer.Length = 0 Then Exit Sub
thisStream.Write(writebuffer, 0, writebuffer.Length)
End Sub

Public Function readStr(ByVal length) As Byte()
Dim readbuffer(4096) As Byte
Dim s As Integer
Dim xs As Integer = 0

Do
If thisStream.DataAvailable = True Then Exit Do
If xs >= 600000 Then Exit Do
xs += 1
Loop

If thisStream.DataAvailable = False Then
Array.Resize(readbuffer, 0)
Return readbuffer
End If
If length > 0 Then s = thisStream.Read(readbuffer, 0, length)
If s = 0 Then Array.Resize(readbuffer, 0)

Return readbuffer
End Function

End Class




' ******* Sample:

Dim myipaddr As System.Net.IPAddress = System.Net.IPAddress.Parse("10.10.10.1")
Dim mysock As System.Net.Sockets.Socket = New System.Net.Sockets.Socket(myipaddr.AddressFamily, Net.Sockets.SocketType.Stream, Net.Sockets.ProtocolType.Tcp)
Dim myendpoint As System.Net.IPEndPoint = New System.Net.IPEndPoint(myipaddr, 8728)

mysock.Connect(myendpoint)
Dim mystream As System.Net.Sockets.NetworkStream = New System.Net.Sockets.NetworkStream(mysock, True)

Dim apiros As ApiRos = New ApiRos(mysock)
apiros.login("Admin", "PaSsWoRd")

Dim xwords(2) As String
xwords(0) = "/tool/user-manager/user/pr"
apiros.writeSentence(xwords)

Dim attr(1024) As String, aval(1024) As String
Dim attrcount As Integer = 0
Dim ist As String
Do While 1
ist = apiros.readSentence()
If Len(ist) = 0 Then
attr(attrcount) = ""
aval(attrcount) = ""
Exit Sub
End If
Loop






Remember to share..................

Re: Mikrotik API and C# ?

Posted: Thu Feb 07, 2008 9:08 pm
by taz
hi,

can you use this ret,password and generate md5 hash (from your working script)? I check this with my md5 algoritm.

string password = 1234
string ret = 8376e40609025e92aabad58d80600888

string HexPass = Hex(password) // result is 31323334
byte[] Bytes = ASCIIEncoding.ASCII.GetBytes("00" + StringToHex(password) + ret);
byte[] md5Hash = md5.ComputeHash(Bytes);
result = md5.ComputeHash(Bytes);

my result > 36a5dc4461c692a2fde146772beefd50


thx

Re: Mikrotik API and C# ?

Posted: Sun Feb 10, 2008 2:47 pm
by tgrand
You have to use the hex to ascii function.
When I attempted to try ASCIIEncoding.ASCII.GetBytes it did not work.

Re: Mikrotik API and C# ?

Posted: Fri Feb 15, 2008 4:29 pm
by tgrand
Taz,

Did you get it working OK?
I have been using it for some time now, and it works great for me.

Todd

Re: Mikrotik API and C# ?

Posted: Fri Feb 15, 2008 4:40 pm
by taz
no :(

Re: Mikrotik API and C# ?

Posted: Fri Feb 15, 2008 5:10 pm
by mrz
I think that problem is here:
ASCIIEncoding.ASCII.GetBytes("00" + StringToHex(password) + ret);

Is "ASCIIEncoding.ASCII.GetBytes()" c# built in function? If so then you should write your own.
Check out what value is returned by this function, probably it's not correct.

Re: Mikrotik API and C# ?

Posted: Fri Feb 15, 2008 5:38 pm
by taz
yes,
ASCIIEncoding.ASCII.GetBytes is built in function . If i use System.text.Encoding.GetBytes , result is identical

how i check value form this function ? what confront ?
string ret = "8376e40609025e92aabad58d80600888";
string password = "1234";
StringToHex(password) return 31323334

byte[] Bytes = ASCIIEncoding.ASCII.GetBytes("00" + StringToHex(password) + ret);
byte[] Bytes1 = System.Text.Encoding.ASCII.GetBytes("00" + StringToHex(password) + ret);
byte[] md5Hash = md5.ComputeHash(Bytes);
string md5New = BitConverter.ToString(md5Hash);

byte[] md5Hash1 = md5.ComputeHash(Bytes1);
string md5New1 = BitConverter.ToString(md5Hash1);
first four byte from md5New > 48-48-51-49
md5New return > 36a5dc4461c692a2fde146772beefd50

first four byte from md5New1 > 48-48-51-49
md5New1 return > 36a5dc4461c692a2fde146772beefd50

if a check output from script and sniffer data on mikrotik its right

:(

Re: Mikrotik API and C# ?

Posted: Fri Feb 15, 2008 9:22 pm
by ekkas
If you use Indy10, (downloadable for free) you can do something similar like I do in Delphi(Pascal):
(Unedited)


function StrToHex(O:String):String;
var i : Integer;
begin
Result:='';
for i:=1 to Length(O) do
begin
Result:=Result+lowercase(IntToHex(Integer(O),2));
end;
end;

Function GetMD5(Source:String):String;
var MD5:TIdHashMessageDigest5;
begin
MD5:=TIdHashMessageDigest5.Create;
try
Result:=MD5.AsHex(MD5.HashValue(Source));
finally
MD5.Free;
end;
end;

function TMikrotikAPI.Connect(TCPClient:TidTCPClient;Host:String;Port:Integer): Boolean;
begin
try
Response.Clear;
Log .Clear;
Client:=TCPClient;
Client.Host:=Host;
Client.Port:=Port;
Client.Connect;
Result:=True
except
Result:=False;
end;
end;

function TMikrotikAPI.LogOn(Username,Password:String): Boolean;
var S : String;
IC: TIdOTPCalculator;
begin
Write('/login');
S:=ReadStr; (*!done*)
S:=ReadStr; (*=ret*)
ReadStr; (*0*)

S:=Copy(S,6,Length(S));
S:=HexToAscii(S);
S:='=response=00'+GetMD5(#0+password+S);
Write('/login'#13#10'=name='+username+#13#10+S);
Read;
Result:=Response[0]='!done';
end;




If you want more, just ask...

Re: Mikrotik API and C# ?

Posted: Fri Feb 15, 2008 11:42 pm
by changeip
My contribution for vb.net below:
    Public Function GetDigest(ByVal ret As String, ByVal password As String) As String

        Dim retbytes() As Byte = h2a("00" & StringToHex(password) & ret) 'convert hexadecimal string to ascii bytes 
        Using md5 As New System.Security.Cryptography.MD5CryptoServiceProvider()
            Return "00" & a2h(md5.ComputeHash(retbytes)).ToLower
        End Using

    End Function
 Private Function StringToHex(ByVal password As String) As String
        Dim retString As String = ""
        Dim stringBytes() As Byte = System.Text.ASCIIEncoding.ASCII.GetBytes(password)
        Dim i As Integer = 0
        For i = 0 To stringBytes.Length - 1
            Dim hexTmp As String = Hex(stringBytes(i))
            If hexTmp.Length = 1 Then
                retString = retString & "0" & hexTmp
            Else
                retString = retString & hexTmp
            End If
        Next
        Return retString
    End Function
  Private Function a2h(ByVal ascii() As Byte) As String
        Dim i As Integer = 0
        Dim ret As String = ""
        For i = 0 To ascii.Length - 1
            Dim tmp As String = Hex(ascii(i))
            If tmp.Length = 1 Then
                ret = ret & "0" & tmp
            Else
                ret = ret & tmp
            End If
        Next
        Return ret
    End Function

    Private Function h2a(ByVal hextext As String) As Byte()
        Dim y As Integer
        Dim num As String
        Dim bytes(16) As Byte
        Dim value As String = ""
        Dim i As Integer = 0
        For y = 0 To 32
            num = Mid(hextext, y + 1, 2)
            value = value & Chr(CInt(Val("&h" & num)))
            bytes(i) = CByte(Val("&h" & num))
            y += 1
            i += 1
        Next y
        Return bytes
    End Function

Re: Mikrotik API and C# ?

Posted: Tue Mar 04, 2008 4:32 pm
by codeb
Question for ekkas

I try to make some HotSpotManager software in Delphi. I this post you write some code for connect and login to MT. If you can , please write code for sending commends like add/remove hotspot user, hotspot profile etc. Also you can send me on bojan@fakat.ba

P.S. Sorry on bad English

Re: Mikrotik API and C# ?

Posted: Tue Mar 04, 2008 5:35 pm
by mrz
Please read api documentation:
http://wiki.mikrotik.com/wiki/API

This is taken from the wiki ( everything is explained ).
# Protocol stream is formatted as a sequence of words.
# Each word is encoded as length, followed by that many bytes of content.
# Words are grouped into sentences. End of sentence is terminated by zero length word.

Are you a programmer or what? If you were able to send /login command and get response, then you already did what you are asking for, just check the code.

Re: Mikrotik API and C# ?

Posted: Tue Mar 04, 2008 6:49 pm
by ekkas
If you use Indy, you can easily modify my Pascal code above.
Then commands are similar to console.

Re: Mikrotik API and C# ?

Posted: Mon Mar 24, 2008 6:24 pm
by cheesegrits
FYI, I posted a perl API client here:

http://forum.mikrotik.com/viewtopic.php?f=9&t=22744

-- hugh