Some SMTP servers require a HELO/EHLO command before a STARTTLS, e.g.: $ telnet mail.sourceforge.net 25 220 mail.sourceforge.net ESMTP Exim 4.44 ... STARTTLS 503 STARTTLS command used when not advertised
for instance, when I try to retrieve the server certificate for mail.sourceforge.net:25 using `-starttls smtp -showcerts': $ openssl s_client -connect mail.sourceforge.net:25 \ -starttls smtp -CApath /etc/ssl/certs -showcerts it fails with an error message like: CONNECTED(00000003) 9829:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:s23_clnt.c:567: The attached patch (against openssl-0.9.8a) adds the `-ehlo' option to s_client: -ehlo hostname - use the EHLO smtp command before issuing STARTTLS (to be used in conjunction with -starttls smtp) with this patch, s_client successfully connects and shows the certificate: $ openssl s_client -connect mail.sourceforge.net:25 -showcerts -starttls smtp -ehlo host.domain -CApath /etc/ssl/certs ... Verify return code: 0 (ok) --- 220 mail.sourceforge.net ESMTP Exim 4.44 Tue, 27 Dec 2005 10:58:18 -0800 sc8-sf-mx1.sourceforge.net 250-mail.sourceforge.net Hello ppp85-140-15-108.pppoe.mtu-net.ru [85.140.15.108] 250-SIZE 1048576 250-EXPN 250-PIPELINING 250-STARTTLS 250 HELP -- Pavel Gorshkov
--- openssl-0.9.8a.orig/apps/s_client.c Sat Oct 1 03:38:19 2005 +++ openssl-0.9.8a/apps/s_client.c Tue Dec 27 18:43:52 2005 @@ -227,6 +227,8 @@ 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\" and \"pop3\" are supported.\n"); + BIO_printf(bio_err," -ehlo hostname - use the EHLO smtp command before issuing STARTTLS\n"); + BIO_printf(bio_err," (to be used in conjunction with -starttls smtp)\n"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err," -engine id - Initialise and use the specified engine\n"); #endif @@ -245,6 +247,7 @@ char *cbuf=NULL,*sbuf=NULL,*mbuf=NULL; int cbuf_len,cbuf_off; int sbuf_len,sbuf_off; + int mbuf_off; fd_set readfds,writefds; short port=PORT; int full_log=1; @@ -261,6 +264,7 @@ SSL_CTX *ctx=NULL; int ret=1,in_init=1,i,nbio_test=0; int starttls_proto = 0; + char *ehlo_hostname=NULL; int prexit = 0, vflags = 0; SSL_METHOD *meth=NULL; #ifdef sock_type @@ -472,6 +476,11 @@ else goto bad; } + else if (strcmp(*argv,"-ehlo") == 0) + { + if (--argc < 1) goto bad; + ehlo_hostname = *++argv; + } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { @@ -717,11 +726,17 @@ cbuf_off=0; sbuf_len=0; sbuf_off=0; + mbuf_off=0; /* This is an ugly hack that does a lot of assumptions */ if (starttls_proto == 1) { - BIO_read(sbio,mbuf,BUFSIZZ); + mbuf_off = BIO_read(sbio,mbuf,BUFSIZZ); + if (ehlo_hostname) + { + BIO_printf(sbio,"EHLO %s\r\n",ehlo_hostname); + BIO_read(sbio,mbuf+mbuf_off,BUFSIZZ-mbuf_off); + } BIO_printf(sbio,"STARTTLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); }