mIRC Home    About    Download    Register    News    Help

Print Thread
#271575 21/04/23 11:47 PM
Joined: Jul 2006
Posts: 4,144
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,144
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,144
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,144
Quote
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,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
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,144
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,144
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,144
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,144
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-
}



Originally Posted by SMTP
> //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:

Originally Posted by IRC
?? :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,144
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,144
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,144
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,144
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,144
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,144
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,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
When the negotiation is complete, the SOCKOPEN event is triggered again, with .starttls set to $true.

Joined: Jul 2006
Posts: 4,144
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,144
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,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
Yes, if the negotiation fails, the SOCKOPEN event should be triggered with an error.

Joined: Jul 2006
Posts: 4,144
W
Wims Offline OP
Hoopy frood
OP Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,144
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,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
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.


Link Copied to Clipboard