|
Post by Chris Iverson on May 24, 2018 9:47:56 GMT -5
Well, I upload my progress to GitHub, at github.com/iversc/lb-schannel-wrapper, if you're interested. The code can be compiled with Visual Studio Community, which is free for individual/home users. I've got most of the client-side code written, but I'm now starting to debug, and the DLL doesn't run without crashes at the moment. I just came across one of the issues causes the crashes, actually; a misuse of one of Win32's memory allocation functions due to bad example code. Rewriting that now. EDIT: And I'm now able to confirm that using mesock32 for TLS communication is NOT going to work. Mesock32 assumes that all data passing through it is standard strings; trying to pass encoded data through causes corruption. In particular, I was able to use WireShark to verify that it cuts off the TLS ClientHello message at the first null byte, and never sends the entire thing, preventing the TLS handshake from going through. I'm going to be doing rewriting to remove mesock32 entirely from the DLL, and switch to using winsock sockets in my DLL. I'll, of course, try to provide a similar interface as mesock for actually opening connections.
|
|
fwm
Full Member
Posts: 105
|
Post by fwm on May 24, 2018 17:17:29 GMT -5
Wow, I will take a look at that now!
Outside of Liberty Basic, I have never compiled or built anything so will give Visual Studio Community a go and see where I get to.
I understand about Mesock32.
Thanks Chris!
Keith.
|
|
fwm
Full Member
Posts: 105
|
Post by fwm on May 25, 2018 0:36:44 GMT -5
Hi Chris, I just downloaded Visual Studio Community and had a go at compiling the DLL. I got a DLL out the other end, but when I tried the test.bas program you have included in the repository, I just got an error message: "Runtime error: The parameter is incorrect. ( OS error 16r57 )" as soon as LB tries to load the DLL. This, I am sure, is because I compiled it incorrectly or have used an incorrect version of something... like I said I am not familiar with Visual Studio and have never built or compiled anything outside of LB before so I think I will leave this to you and the other experts and await a copy of the DLL built by someone who knows what they are doing! Keith.
|
|
|
Post by Carl Gundel on May 29, 2018 14:58:30 GMT -5
Hi Chris, I just downloaded Visual Studio Community and had a go at compiling the DLL. I got a DLL out the other end, but when I tried the test.bas program you have included in the repository, I just got an error message: "Runtime error: The parameter is incorrect. ( OS error 16r57 )" as soon as LB tries to load the DLL. This, I am sure, is because I compiled it incorrectly or have used an incorrect version of something... like I said I am not familiar with Visual Studio and have never built or compiled anything outside of LB before so I think I will leave this to you and the other experts and await a copy of the DLL built by someone who knows what they are doing! Keith. Is it possible that you compiled a 64-bit DLL instead of a 32-bit one?
|
|
fwm
Full Member
Posts: 105
|
Post by fwm on May 29, 2018 16:02:18 GMT -5
Hi Carl, In all honesty - I have no idea! I may very well have done that without realising, and I'm not sure what I would need to change to correct this. I probably need to have another go with Visual Studio open in front of me, and dig around to find where I make the necessary changes. If I manage to work it out I will report back Keith.
|
|
|
Post by Chris Iverson on May 29, 2018 16:34:22 GMT -5
That would be the only thing I could think of that would cause LB to not load the DLL. Although not functional, the DLL as-is should at least load in LB, if compiled Debug x86. Haven't tried a release build yet, and for obvious reasons, won't be building 64-bit. (In comboboxes near the top of the VS GUI, you can specify whether or not to build the DLL as a Debug or Release build, and whether to build it as a 32(x86) or 64-bit(x64) DLL.)
Out of curiosity, I did a rebuild of the DLL in 64-bit, and sure enough, I got that same error.
I should note that, if built properly, you shouldn't have to copy the resulting DLL anywhere or edit the LB test.bas to get it to run. The x86 debug output folder is the one that test.bas should look in, as written.
Haven't had much of a chance to add to this; holiday weekend, the release of Dark Souls Remastered, and a server borking itself at work kept me busy.
|
|
fwm
Full Member
Posts: 105
|
Post by fwm on May 29, 2018 19:21:31 GMT -5
Hi Chris,
Yes, I think it's safe to assume I really don't know what I'm doing with Visual Studio... but it's interesting to start learning in this way! I haven't had a chance to go back to try compiling it again yet but I will follow your recommendations.
Same here in the UK, it's been a holiday weekend and some nice weather!
I am really looking forward to the moment when this all comes together - wow! Liberty Basic can speak TLS/SSL!
Keith.
|
|
|
Post by Chris Iverson on May 29, 2018 20:39:50 GMT -5
I'm planning on making it so it can do non-TLS communication, as well, so it can function as a complete replacement for Mesock, for 2 reasons.
1) So you don't need another library if you're doing non-TLS network stuff, and 2) So you can transfer binary data.
With the testing I've done with Mesock, it will not handle transfer of anything except string-like data well. Basic communication is possible, but not transferring files with special characters in them, not encoded/compressed data(gzip is a common one), and not any binary protocols(HTTP/2)
I don't expect this to add much time to the project; considering I have to be able to transfer data over sockets anyway, adding an interface to the DLL for the library user to do so directly seems a no-brainer.
Let me know if you have any questions about any part of the code; I'd be happy to go over what I wrote and why. (It occurs to me that I probably could've and should've added more comments.)
|
|
fwm
Full Member
Posts: 105
|
Post by fwm on May 31, 2018 5:48:11 GMT -5
Hi Chris, I can see how that makes sense. I'll wait until you have chance to update the Github code and then I'll have a look - I'm sure I will be able to think of some questions to ask Again, thanks for your time on this. Keith.
|
|
|
Post by Chris Iverson on May 31, 2018 15:15:06 GMT -5
Well, basic (client) sockets functionality is now complete. (Server-side code hasn't been written yet.) New code's been published to GitHub, along with test LB code that is working for me. API for basic sockets so far: Connect(host$, srv$) Connects to the specified host on the specified service port, and returns a Winsock socket tied to the connection. host$ can specify an IPv4/v6 address or a domain name. srv$ can specify a service name("http", "https", etc), or a port number("80", "443"). Well-known services that have defined ports will attempt connections on those ports. I haven't had a chance to test it yet, but the way the code is written, this should work with both IPv4 and IPv6, if both ends of the connection support it. It will default to whichever one the system returns first, if it returns a list of possible connections. Returns a socket handle, or the INVALID_SOCKET value(should be -1) if the connection fails. If the function returns -1, you can call GetError() for a more specific error code. CloseSocket(sock) Closes the specified socket that was returned in a Connect() call. GetError() No parameter. Used to return an API error when the error code cannot be returned directly(such as when the return value is a socket or other ambiguous type) Send(socket, msg$, msgLen) Sends the specified msg$ out over the specified socket. Socket is returned from the Connect() call. msg$ can be any type of data, held as an LB string. msgLen is the length, in bytes, of the message you're sending. This function returns the number of bytes successfully sent(which lets you know if part of a message needs to be resent, if the returned number of bytes is less than msgLen). If the send failed, this function returns -1, and you can get a more specific error code by calling GetError(). Receive(socket, buf$, bufLen) Receives data from the specified socket, and stores it in buf$. This requires preallocating a buffer to fill, as well as knowing the size of the buffer. That way, the system doesn't try to receive more data than you are prepared to handle. The return value will be the number of bytes read from the connection if successful. Zero is still a success, but it means that the server you're connected to closed the connection. At this point, you can only, and must, close your end of the socket yourself. -1 is a failure, and a more specific error code can be obtained from GetError().
|
|
|
Post by Alyce Watson on May 31, 2018 15:36:13 GMT -5
Chris, this is beyond impressive.
|
|
|
Post by Chris Iverson on May 31, 2018 18:25:03 GMT -5
Well, this is unexpected.
Client-side, unverified TLS is now working in my DLL. GitHub's got the latest changes, including the LB test code that successfully connects to my webserver over HTTPS and retrieves the index page.
Overall, it took less effort than I anticipated to modify the existing code to use Winsock sockets(though I did run into some issues I hadn't before, due to not being able to test a full connection before).
The LB test code's honestly a bit of a mess right now, since I was more focused on actually using it than making it easier to use in the future. However, it should at least demonstrate that the DLL is fully functional.
|
|
fwm
Full Member
Posts: 105
|
Post by fwm on Jun 1, 2018 13:37:38 GMT -5
Hi Chris, This is incredible! You sir are a genius! As soon as I saw your message above I had another go at building the DLL, this time correctly as a 32-bit DLL, and of course it works straight away in LB. I have spent the last few hours working through your demo code and have tested it out by getting it to speak to my SMTP server via the SSL/TLS port and it worked perfectly! I am going to keep playing with this, and also I haven't tried the non-TLS functions yet which should replace the use of mesock, but I will have a go with that next! I believe that you have created something that is game-changing here, and I heartily applaud you for your efforts Keith.
|
|
fwm
Full Member
Posts: 105
|
Post by fwm on Jun 1, 2018 13:50:22 GMT -5
And there we have it - just tested it as a replacement for mesock (using the four functions Connect, CloseSocket, Send and Receive) and works just like mesock does.
Just wondering if there's any way to put the "timeout" into the Connect function, so there's a way to specify how long it tries to connect for before aborting?
Keith
|
|
|
Post by Chris Iverson on Jun 1, 2018 14:05:52 GMT -5
Specifying a timeout should be easy enough. While all sockets are blocking by default(i.e. they halt your program's execution until the call completes), all sockets can be set to a non-blocking mode. I'll probably make that it's own API call, something like ConnectTimeout(), and leave the current Connect() as it is.
|
|