You need to send both the length and the actual string which is that many bytes long.
From your example, it seems you’re sending just the length byte, but never the actual message. You don’t get any reply, because RouterOS is still waiting for the bytes you told it to wait for. i.e. you send 0x06, but you never send “/login” through the socket.
But anyway… Why make a “frontend”? Having the web client see the RouterOS password would be bad if the app is publically visible. Having it be at the backend ensures nobody sees it.
thank you for the help,
i am a developer of html javascript php etc but i dont really deal with sockets and bytes etc… so maybe abit more googline is in order
when i mean frontend, i want to write a html app that can connect to the mikrotik to get me stats etc, but i dont want to require a server
my idea was to use tcp sockets for javascript, bootstrap framework, then i can create a mobile app with phonegap/cordova
this is purely for our own use and maybe resell if i can get it working correct
Oh, so a mobile app, not a web app, I see. Well, in that case, it’s limited to the device, so yeah, you could have it at JavaScript.
I’d think you can use NodeJS client as a starting point, seeing that the core language APIs are almost the same. Just replace its sockets with the chrome sockets or whatever, and you should be done with it.
Just add another call to chrome.sockets.tcp.send that sends “message”, or better yet, make a single call that sends “abc + message”, rather than just “abc”.
Oooh… I see. So the buffer is the thing that needs to be sent, and has to contain all the data, and the constructor of ArrayBuffer is just the size (I thought it was the initial content).
Well then, in that case… it seems what you’re actually doing is the opposite - you have the data “/login”, but you don’t have the length sent before that. Your buffer needs to also have an additional 1 byte to store the encoded length in.
In the end, you need to send the sequence
0x06 0x2F 0x6C 0x6F 0x67 0x69 0x6E
over the socket, but you’re instead sending
0x2F 0x6C 0x6F 0x67 0x69 0x6E
meaning that RouterOS expects you to send far more bytes before it starts responding.
Soo… maybe
function str2ab2(message){
//TODO: Encode word length according to the spec
var encodedLength = message.length;
var buffer = new ArrayBuffer(1/*byte length of the binary representation of encodedLength ?*/ + message.length);
var bufferView = new Uint8Array(buffer);
bufferView[0] = encodedLength;
for (var i = 1; i <= message.length; ++i) {
bufferView[i] = message.charCodeAt(i);
}
return buffer;
}
i get the mikrotik to reply cannot login in, and i get a failed login in the logs
for some reason my challenge that is getting returned i cant convert it correctly to get its values?
example nodejs: =ret=cf 94 f9 5d 81 b0 fb 04 3e 01 8c 59 ec e6 fc 18 - focus on the 81
0x81
129

exmaple javascript: =ret=fc da 81 0e 23 8e d1 3e 77 f5 0e 93 0c 08 f9 34 - again focus on the 81
[Log] 0x81 (index.js, line 96)
[Log] 129 (index.js, line 97)
[Log] (index.js, line 98)
any idea how i achieve getting the correct symbol?
also is this correct how i should be returning my response?
=response=“00”+CryptoJS.MD5(String.fromCharCode(0)+vars.pass+challenge);
The challenge is a hex string that needs to be transformed to a binary string (which you can do by hex decoding the hex string), while the MD5 needs to be outputted in hex (which it seems CryptoJS already does…).
I think CryptoJS is referring to that as a “Latin1” encoding format… Just for a test drive prior, I tested everything with the string “apple”. It’s hash MD5 is “1f3870be274f6c49b3e31a0c6728957f” and the binary string of that hash is “8p¾’OlI³ãg(•”.
After confirming the above, I believe you should be able to do it with
BTW, now is as good as time as any to ask you… Please consider publishing your API client when you have it in some semi-useful state, and consider making it NodeJS compatible too, by adding a conditional “module.export” at the end.
Im still having no look and I just don’t no what I’m doing wrong
var thechallenge = data[1].substring(5); // 7e3f5affe828fd31f9d0b83f163c33c7
var x = CryptoJS.enc.Hex.parse(thechallenge).toString(CryptoJS.enc.Latin1); // ~?Zÿè(ý1ùи?<3Ç
var y = CryptoJS.MD5(String.fromCharCode(0)+vars.pass+x).toString(); // 457fe6ec93b698a9dc027734058f6b67
var response = "=response=00"+y; // =response=00457fe6ec93b698a9dc027734058f6b67
reply from mikrotik is !trap=message=cannot log in!done
The full thing that needs to go on the network after you get the challenge is ANOTHER /login (prefixed with its encoded length), followed by the response attribute word (prefixed with its encoded length), followed by a null byte (a.k.a. a zero length word). Are you sure you’re sending all of this? If you’re only sending the attribute word, that can get you this error.
which logs are you referring to, is it possible to enable debug on the mikrotik router and see what it is receiving and decoding as?
this is my javascript logs:
[Log] done (index.js, line 190)
[Log] ["done", "=ret=b4fb9b6b1245780d464e3d9091e77bc4"] (2) (index.js, line 205)
[Log] b4fb9b6b1245780d464e3d9091e77bc4 (index.js, line 102)
[Log] ´ûkExFN=ç{Ä (index.js, line 162)
[Log] 329664b76a9a3b8bee007aeb7565cf66 (index.js, line 164)
[Log] =response=00329664b76a9a3b8bee007aeb7565cf66 (index.js, line 166)
[Log] ArrayBuffer {byteLength: 7} (index.js, line 18)
[Log] {bytesSent: 7, resultCode: 0} (index.js, line 168)
[Log] ArrayBuffer {byteLength: 12} (index.js, line 18)
[Log] {bytesSent: 12, resultCode: 0} (index.js, line 170)
[Log] ArrayBuffer {byteLength: 45} (index.js, line 18)
[Log] {bytesSent: 45, resultCode: 0} (index.js, line 172)
[Log] ArrayBuffer {byteLength: 1} (index.js, line 18)
[Log] {bytesSent: 1, resultCode: 0} (index.js, line 174)
[Log] !trap=message=cannot log in!done (index.js, line 28)
when i use wireshark and sniff the packets that get sent,
i can see from my laptop that it sends the individual bytes correctly as
/login =user=admin =response=00329664b76a9a3b8bee007aeb7565cf66
The other possibilities are that the sentence was ok, but login was refused. The API user needs to have the “api” permission, the address property needs to be empty or otherwise allow for your IP… and needless to say your password must be correct.
Try to login with another API client, and see if you get the same result.
I have created a test user with a group of test and only allowing api = not working
tried another mikrotik router with different credentials and ip addresses = not working
but yet if i use another api client, like NodeJS,php,java, it works fine!