Some IRCds are starting to support STARTLS. This patch adds support to
s_client. It is tested successfully with:

$ openssl s_client -starttls irc -connect irc.unrealircd.org:6667
$ openssl s_client -starttls irc -connect irc.inspircd.org:6667
WARNING: can't open config file: /usr/local/ssl/openssl.cnf
CONNECTED(00000003)
depth=0 C = CA, ST = Toronto, L = Toronto, O = ChatSpike, OU = IRC, CN = Brain, 
emailAddress =
...

It successfully detects IRCds which currently do not support STARTTLS
(this list will probably be reduced in time). For most IRCds, before
registration the IRCd will not give the client any response for what
it deems unknown commands:

$ openssl s_client -starttls irc -connect irc.efnet.net:6667
$ openssl s_client -starttls irc -connect irc.oftc.net:6667
$ openssl s_client -starttls irc -connect irc.freenode.net:6667
WARNING: can't open config file: /usr/local/ssl/openssl.cnf
CONNECTED(00000003)
Timeout waiting for IRCd response (8s).
Server did not respond positively (numeric=670) to STARTTLS.
...

Other IRCds, such as UnrealIRCd, will make noise when they see
commands they don't recognize before registration, so for them the
timeout behavior is not necessary:

$ openssl s_client -starttls irc -connect irc.ohnopub.net:6667
WARNING: can't open config file: /usr/local/ssl/openssl.cnf
CONNECTED(00000003)
IRCd declares that it doesn't support STARTTLS: :irc.retro-box.net 451 STARTTLS 
:You have not registered
Server did not respond positively (numeric=670) to STARTTLS.

-- 
binki

Look out for missing or extraneous apostrophes!

? crypto/aes/aesni-sha1-x86_64.s
? crypto/aes/aesni-x86_64.s
? crypto/aes/bsaes-x86_64.s
? crypto/aes/vpaes-x86_64.s
? crypto/bn/modexp512-x86_64.s
? crypto/bn/x86_64-gf2m.s
? crypto/bn/x86_64-mont5.s
? crypto/modes/ghash-x86_64.s
Index: apps/s_client.c
===================================================================
RCS file: /v/openssl/cvs/openssl/apps/s_client.c,v
retrieving revision 1.142
diff -u -b -B -r1.142 s_client.c
--- apps/s_client.c     14 Dec 2011 22:17:05 -0000      1.142
+++ apps/s_client.c     20 Dec 2011 20:25:33 -0000
@@ -190,6 +190,8 @@
 #undef BUFSIZZ
 #define BUFSIZZ 1024*8
 
+#define S_CLIENT_IRC_READ_TIMEOUT (8)
+
 extern int verify_depth;
 extern int verify_error;
 extern int verify_return_error;
@@ -344,7 +346,7 @@
        BIO_printf(bio_err," -starttls prot - use the STARTTLS command before 
starting TLS\n");
        BIO_printf(bio_err,"                 for those protocols that support 
it, where\n");
        BIO_printf(bio_err,"                 'prot' defines which one to 
assume.  Currently,\n");
-       BIO_printf(bio_err,"                 only \"smtp\", \"pop3\", \"imap\", 
\"ftp\" and \"xmpp\"\n");
+       BIO_printf(bio_err,"                 only \"smtp\", \"pop3\", \"imap\", 
\"irc\", \"ftp\" and \"xmpp\"\n");
        BIO_printf(bio_err,"                 are supported.\n");
 #ifndef OPENSSL_NO_ENGINE
        BIO_printf(bio_err," -engine id    - Initialise and use the specified 
engine\n");
@@ -545,6 +547,7 @@
        PROTO_SMTP,
        PROTO_POP3,
        PROTO_IMAP,
+       PROTO_IRC,
        PROTO_FTP,
        PROTO_XMPP
 };
@@ -912,6 +915,8 @@
                                starttls_proto = PROTO_POP3;
                        else if (strcmp(*argv,"imap") == 0)
                                starttls_proto = PROTO_IMAP;
+                       else if (strcmp(*argv, "irc") == 0)
+                               starttls_proto = PROTO_IRC;
                        else if (strcmp(*argv,"ftp") == 0)
                                starttls_proto = PROTO_FTP;
                        else if (strcmp(*argv, "xmpp") == 0)
@@ -1455,6 +1460,68 @@
                BIO_printf(sbio,". STARTTLS\r\n");
                BIO_read(sbio,sbuf,BUFSIZZ);
                }
+       else if (starttls_proto == PROTO_IRC)
+               {
+               int numeric;
+               BIO *fbio = BIO_new(BIO_f_buffer());
+               BIO_push(fbio, sbio);
+
+               BIO_printf(fbio, "STARTTLS\r\n");
+               (void)BIO_flush(fbio);
+
+               width = SSL_get_fd(con) + 1;
+
+               do
+                       {
+                       numeric = 0;
+
+                       FD_ZERO(&readfds);
+                       openssl_fdset(SSL_get_fd(con), &readfds);
+                       timeout.tv_sec = S_CLIENT_IRC_READ_TIMEOUT;
+                       timeout.tv_usec = 0;
+                       /*
+                        * If the IRCd doesn't respond within
+                        * S_CLIENT_IRC_READ_TIMEOUT seconds, assume
+                        * it doesn't support STARTTLS. Many IRCds
+                        * will not give _any_ sort of response to a
+                        * STARTTLS command when it's not supported.
+                        */
+                       if (!BIO_get_buffer_num_lines(fbio)
+                           && !BIO_pending(fbio) && !BIO_pending(sbio)
+                           && select(width, (void *)&readfds, NULL, NULL, 
&timeout) < 1)
+                               {
+                               BIO_printf(bio_err, "Timeout waiting for IRCd 
response (%ds).\n", S_CLIENT_IRC_READ_TIMEOUT);
+                               break;
+                               }
+
+                       mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
+                       if (mbuf_len < 1)
+                               break;
+
+                       (void)sscanf(mbuf, "%*s %d", &numeric);
+                       /* :example.net 451 STARTTLS :You have not registered */
+                       /* :example.net 421 STARTTLS :Unknown command */
+                       if ((numeric == 451 || numeric == 421)
+                           && strstr(mbuf, "STARTTLS"))
+                               {
+                               BIO_printf(bio_err, "IRCd declares that it 
doesn't support STARTTLS: %s", mbuf);
+                               break;
+                               }
+                       }
+               while (numeric != 670);
+
+               (void)BIO_flush(fbio);
+               BIO_pop(fbio);
+               BIO_free(fbio);
+
+               if (numeric != 670)
+                       {
+                       BIO_printf(bio_err,
+                                  "Server did not respond positively 
(numeric=670) to STARTTLS.\n");
+                       ret = 1;
+                       goto shut;
+                       }
+               }
        else if (starttls_proto == PROTO_FTP)
                {
                BIO *fbio = BIO_new(BIO_f_buffer());

Attachment: pgpc9poenY41B.pgp
Description: PGP signature

Reply via email to