|
Joined: Jul 2006
Posts: 4,222
Hoopy frood
|
OP
Hoopy frood
Joined: Jul 2006
Posts: 4,222 |
While I can get /server -t to work on irc server supporting STARTTLS (such as swiftirc.net)
There seems to be a missing support for STARTTLS in the implementation with /sockopen -t. Depending on the protocol used, the moment where the TLS handshake needs to occur is unknown to mIRC, but let's take an IRC server.
If i try to script /server -t with /sockopen -t, I need to send 'starttls' to the irc server before sending nick and user message, this message is sent non encrypted, it works, the server answer ":tardis.en.uk.SwiftIRC.net 670 * :STARTTLS successful, go ahead with TLS handshake" at which point the TLS handshake needs to occur but I don't know how mIRC could guess it's time, it seems to me I would need to indicate mIRC that now is the time.
Has anyone ever used /sockopen -t successfully? I believe we need a parameter on /sockwrite to initiate the handshake but not sure.
#mircscripting @ irc.swiftirc.net == the best mIRC help channel
|
|
|
|
Joined: Jul 2006
Posts: 4,222
Hoopy frood
|
OP
Hoopy frood
Joined: Jul 2006
Posts: 4,222 |
I believe we need a parameter on /sockwrite to initiate the handshake but not sure. A new switch, not a new parameter.
#mircscripting @ irc.swiftirc.net == the best mIRC help channel
|
|
|
|
Joined: Dec 2002
Posts: 5,524
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 5,524 |
Your script will need to connect as usual using /sockopen and read the server messages in the SOCKREAD event. If the server sends a message that indicates it supports STARTTLS, you can use /sockopen -t at that point in the SOCKREAD event to initiate the negotiation.
|
|
|
|
Joined: Jul 2006
Posts: 4,222
Hoopy frood
|
OP
Hoopy frood
Joined: Jul 2006
Posts: 4,222 |
Thanks. Quite counter intuitive that one!
Just to be clear, /sockopen -t is not required to be executed inside the on sockread event, the negociation can be initiated whenever one wants.
#mircscripting @ irc.swiftirc.net == the best mIRC help channel
|
|
|
|
Joined: Jul 2006
Posts: 4,222
Hoopy frood
|
OP
Hoopy frood
Joined: Jul 2006
Posts: 4,222 |
Follow up, while /sockopen -t worked for me with an irc server, the original topic at hand was to be able to send an email using outlook smtp server (which does not support SSL directly, only STARTTLS, yeah don't ask me why). When I try though, the smtp server close the connection pretty much as soon as I execute /sockopen -t Start the connection with //sockopen sendmail smtp.office365.com 587 on *:sockclose:sendmail:echo -sg socket closed sockclose on *:sockopen:sendmail:if ($sockerr) echo -sg sockerr in sockopen $sock($sockname).wsmsg on *:sockread:sendmail:{ if ($sockerr) { echo -sg socker error in sockread $sock($sockname).wsmsg return } var %temptext sockread %temptext if (!$sockbr) return tokenize 32 %temptext echo -stg ?? $1- } > //sockopen sendmail smtp.office365.com 587 [04:17:52] ?? 220 LO4P123CA0604.outlook.office365.com Microsoft ESMTP MAIL Service ready at Mon, 24 Apr 2023 02:17:51 +0000 > //sockwrite -n sendmail EHLO [04:17:55] ?? 250-LO4P123CA0604.outlook.office365.com Hello [2a01:cb04:bc:be00:7d67:cbe8:9da0:a279] [04:17:55] ?? 250-SIZE 157286400 [04:17:55] ?? 250-PIPELINING [04:17:55] ?? 250-DSN [04:17:55] ?? 250-ENHANCEDSTATUSCODES [04:17:55] ?? 250-STARTTLS [04:17:55] ?? 250-8BITMIME [04:17:55] ?? 250-BINARYMIME [04:17:55] ?? 250-CHUNKING [04:17:55] ?? 250 SMTPUTF8 > //sockwrite -n sendmail STARTTLS [04:18:21] ?? 220 2.0.0 SMTP server ready > //sockopen -t sendmail socket closed sockclose I believe mIRC is doing the correct job and that the smtp server is broken, but I have no idea. But yeah, trying with IRC, when you tell the IRC server that you want to use STARTTLS, the raw 670 reply is very clear that you need to initiate the handshake and only then the server starts the process again (second Looking up your hostname) whereas the smtp server reinitialize the process before I use /sockopen -t: ?? :tardis.en.uk.SwiftIRC.net NOTICE * :*** Looking up your hostname... ?? :tardis.en.uk.SwiftIRC.net NOTICE * :*** Found your hostname (cached) ?? :tardis.en.uk.SwiftIRC.net NOTICE * :*** Checking ident... ?? :tardis.en.uk.SwiftIRC.net NOTICE * :*** No ident response; username prefixed with ~ > sending starttls ?? :tardis.en.uk.SwiftIRC.net 670 * :STARTTLS successful, go ahead with TLS handshake > executing sockopen -t ?? :tardis.en.uk.SwiftIRC.net NOTICE * :*** Looking up your hostname... ?? :tardis.en.uk.SwiftIRC.net NOTICE * :*** Checking ident... ?? :tardis.en.uk.SwiftIRC.net NOTICE * :*** No ident response; username prefixed with ~ > sending nick vimse ?? PING :D8C6C227 > sending USER Ouims 0 * :. > sending pong D8C6C227 ?? :tardis.en.uk.SwiftIRC.net 001 vimse :Welcome to the SwiftIRC IRC Network vimse!~Ouims@whatever ?? :tardis.en.uk.SwiftIRC.net NOTICE vimse :*** Your TLS certificate fingerprint is whatever ?? :vimse MODE vimse :+ixz
#mircscripting @ irc.swiftirc.net == the best mIRC help channel
|
|
|
|
Joined: Jul 2006
Posts: 4,222
Hoopy frood
|
OP
Hoopy frood
Joined: Jul 2006
Posts: 4,222 |
Update.
I wasn't using the one of latest beta which has openssl 3.0. with latest beta, everything works, just sent a test email using starttls and outlook.
Here is a script to send email for outlook and gmail (for gmail, one needs to enable two way auth in google settings as well as generate a password for third party app)
noop $sendmail(o,mail,pass,mailto,subject,mailcontent) for outlook noop $sendmail(g,mail,pass,mailto,subject,mailcontent) for gmail
alias sendmail { ;$sendmail([og],mail,pass,mailto,subject,mailcontent) sockclose mailing if ($1 == o) sockopen mailing smtp.office365.com 587 elseif ($1 == g) sockopen -e mailing smtp.gmail.com 465 else echo -sg * $!sendmail: invalid service sockmark mailing 0 hadd -m mail service $1 hadd mail mail $2 hadd mail pass $3 hadd mail mailto $4 hadd mail subject $5 hadd mail mailcontent $6 } on *:sockopen:mailing:if ($sockerr) echo -sg * $!sendmail cannot connect to the smtp server on *:sockread:mailing:{ if ($sockerr) { echo -sg * $!sendmail an error occured while reading data from the smtp server: $sock($sockname).wsmsg | return } var %tmp,%m $sock($sockname).mark sockread %tmp if (!$sockbr) return tokenize 32 %tmp if (!%m) && ($1 == 220) { if ($hget(mail,service) == g) { sockwrite -n $sockname HELO mIRC sockmark $sockname 1 } elseif ($v1 == o) { sockwrite -n $sockname $+(EHLO mIRC,$crlf,STARTTLS) sockmark $sockname -1 } } elseif (%m == -1) && ($1 == 220) { sockopen -t mailing .timer -m 1 1600 sockwrite -n mailing EHLO mIRC $(|) sockmark mailing 1 } elseif (%m == 1) && ($1 == 250) { sockwrite -n $sockname AUTH LOGIN sockmark $sockname 2 } elseif (%m == 2) && ($1 == 334) { sockwrite -n $sockname $encode($hget(mail,mail),m) sockmark $sockname 3 } elseif (%m == 3) && ($1 == 334) { sockwrite -n $sockname $encode($hget(mail,pass),m) sockmark $sockname 4 } elseif (%m == 4) && ($1 == 235) { sockwrite -n $sockname MAIL FROM: < $+ $hget(mail,mail) $+ > sockmark $sockname 5 } elseif (%m == 5) { sockwrite -n $sockname RCPT TO: < $+ $hget(mail,mailto) $+ > sockmark $sockname 6 } elseif (%m == 6) && ($1 == 250) { sockwrite -n $sockname DATA sockmark $sockname 7 } elseif (%m == 7) && ($1 == 354) { sockwrite -n $sockname $+(SUBJECT: $hget(mail,subject),$crlf,$crlf,$replace($hget(mail,mailcontent),$+($crlf,.,$crlf),$+($crlf,..,$crlf)),$crlf,.,$crlf,QUIT) echo -sg * $!sendmail: email was sent successfully hfree mail } }
Last edited by Wims; 24/04/23 11:16 AM.
#mircscripting @ irc.swiftirc.net == the best mIRC help channel
|
|
|
|
Joined: Jul 2006
Posts: 4,222
Hoopy frood
|
OP
Hoopy frood
Joined: Jul 2006
Posts: 4,222 |
Khaled, I do believe however that we need an event to know when the handshake is complete, otherwise the smtp server is capricious if I send data too quickly after /sockopen -t. 800ms fails but 1000ms works for example. What do you think?
#mircscripting @ irc.swiftirc.net == the best mIRC help channel
|
|
|
|
Joined: Jul 2006
Posts: 4,222
Hoopy frood
|
OP
Hoopy frood
Joined: Jul 2006
Posts: 4,222 |
I tried to script the event myself with on sockwrite and $sock().starttls which does switch to reporting $true after the handshake is made but the problem is that since no data is sent from the scripter, on sockwrite doesn't trigger. And the handshake can in fact take up to 1500ms so relying on a timer is really not advised to.
#mircscripting @ irc.swiftirc.net == the best mIRC help channel
|
|
|
|
Joined: Dec 2002
Posts: 5,524
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 5,524 |
When the negotiation is complete, the SOCKOPEN event is triggered again, with .starttls set to $true.
|
|
|
|
Joined: Jul 2006
Posts: 4,222
Hoopy frood
|
OP
Hoopy frood
Joined: Jul 2006
Posts: 4,222 |
Ah ok it's already there, cool. Is it possible for the handshake to fail, which would then trigger on sockopen a second time with $sockerr set? would $sockerr take a new value?
#mircscripting @ irc.swiftirc.net == the best mIRC help channel
|
|
|
|
Joined: Dec 2002
Posts: 5,524
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 5,524 |
Yes, if the negotiation fails, the SOCKOPEN event should be triggered with an error.
|
|
|
|
Joined: Jul 2006
Posts: 4,222
Hoopy frood
|
OP
Hoopy frood
Joined: Jul 2006
Posts: 4,222 |
Are you sure on sockopen is meant to trigger when the negociation fails? I cannot get on sockopen to trigger a second time with $sockerr set when the negotiation fails. When I try to fake a server having SSL capability (socklisten -e has been suggested!), the client trying to negociate with /sockopen -t does not get its socket triggering on sockopen a second time, instead on sockclose triggers with $sockerr set to 5 (winsock error is 10101 host disconnected).
on *:socklisten:listen:if (!$sockerr) sockaccept client1 | sockclose listen
alias teststarttls socklisten -d 0.0.0.0 listen $1 | sockopen -d 0.0.0.0 client 127.0.0.1 $1
on *:sockopen:client:{ if (!$sockerr) { if (!$sock(client).starttls) { sockopen -t client echo -sg here start negoc } else echo -sg starttls negoc success } elseif ($sock(client).starttls) echo -sg starttls fail $sockerr $sock(client).wsmsg else echo -sg cannot connect initially }
on *:sockread:client1:{ if ($sockerr) { echo -sg client socket read error!! $sock(client).wsmsg return } echo -sg $sock($sockname).rq sockread $sock(client).rq &a if (!$sockbr) return else echo -sg read $sockbr : $bvar(&a,1-) } on *:sockclose:client:echo -sg sockclose $sockerr $sock(client).wsmsg /teststarttls 8080 You'll have to close the sockets client1 manually and maybe more if you need to test more than once. After /sockopen -t client, the server will receive data, at this point I copy the data and do //bset &a -1 <paste the bytes here> | sockwrite client1 &a
#mircscripting @ irc.swiftirc.net == the best mIRC help channel
|
|
|
|
Joined: Dec 2002
Posts: 5,524
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 5,524 |
Sorry, I meant to say it triggers the SOCKCLOSE event with an error. This feature was implemented/tested around ten years ago. At the time we likely decided that it should trigger the SOCKCLOSE event because the socket was already open and connected at that point. Another design decision was to make it fail gracefully and to not allow the connection to continue insecurely, since the point of requesting STARTTLS is to secure the connection.
|
|
|
|
|