Add Sieve support (RFC 5804) to s_client ("-starttls sieve")

Reviewed-by: Andy Polyakov <appro@openssl.org>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2300)
This commit is contained in:
Robert Scheck 2017-02-09 22:20:59 +01:00 committed by Rich Salz
parent b08ee30bf4
commit 20967afb7f
5 changed files with 82 additions and 14 deletions

View File

@ -2664,3 +2664,11 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
} }
return 1; return 1;
} }
void make_uppercase(char *string)
{
int i;
for (i = 0; string[i] != '\0'; i++)
string[i] = toupper((unsigned char)string[i]);
}

View File

@ -559,6 +559,8 @@ int raw_write_stdout(const void *, int);
# define TM_STOP 1 # define TM_STOP 1
double app_tminterval(int stop, int usertime); double app_tminterval(int stop, int usertime);
void make_uppercase(char *string);
typedef struct verify_options_st { typedef struct verify_options_st {
int depth; int depth;
int quiet; int quiet;

View File

@ -2141,8 +2141,7 @@ static int get_certificate_status(const char *serial, CA_DB *db)
} }
/* Make it Upper Case */ /* Make it Upper Case */
for (i = 0; row[DB_serial][i] != '\0'; i++) make_uppercase(row[DB_serial]);
row[DB_serial][i] = toupper((unsigned char)row[DB_serial][i]);
ok = 1; ok = 1;

View File

@ -749,7 +749,8 @@ typedef enum PROTOCOL_choice {
PROTO_IRC, PROTO_IRC,
PROTO_POSTGRES, PROTO_POSTGRES,
PROTO_LMTP, PROTO_LMTP,
PROTO_NNTP PROTO_NNTP,
PROTO_SIEVE
} PROTOCOL_CHOICE; } PROTOCOL_CHOICE;
static const OPT_PAIR services[] = { static const OPT_PAIR services[] = {
@ -764,6 +765,7 @@ static const OPT_PAIR services[] = {
{"postgres", PROTO_POSTGRES}, {"postgres", PROTO_POSTGRES},
{"lmtp", PROTO_LMTP}, {"lmtp", PROTO_LMTP},
{"nntp", PROTO_NNTP}, {"nntp", PROTO_NNTP},
{"sieve", PROTO_SIEVE},
{NULL, 0} {NULL, 0}
}; };
@ -1911,12 +1913,12 @@ int s_client_main(int argc, char **argv)
*/ */
int foundit = 0; int foundit = 0;
BIO *fbio = BIO_new(BIO_f_buffer()); BIO *fbio = BIO_new(BIO_f_buffer());
BIO_push(fbio, sbio); BIO_push(fbio, sbio);
/* Wait for multi-line response to end from LMTP or SMTP */ /* Wait for multi-line response to end from LMTP or SMTP */
do { do {
mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
} } while (mbuf_len > 3 && mbuf[3] == '-');
while (mbuf_len > 3 && mbuf[3] == '-');
if (starttls_proto == (int)PROTO_LMTP) if (starttls_proto == (int)PROTO_LMTP)
BIO_printf(fbio, "LHLO %s\r\n", ehlo); BIO_printf(fbio, "LHLO %s\r\n", ehlo);
else else
@ -1930,14 +1932,13 @@ int s_client_main(int argc, char **argv)
mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
if (strstr(mbuf, "STARTTLS")) if (strstr(mbuf, "STARTTLS"))
foundit = 1; foundit = 1;
} } while (mbuf_len > 3 && mbuf[3] == '-');
while (mbuf_len > 3 && mbuf[3] == '-');
(void)BIO_flush(fbio); (void)BIO_flush(fbio);
BIO_pop(fbio); BIO_pop(fbio);
BIO_free(fbio); BIO_free(fbio);
if (!foundit) if (!foundit)
BIO_printf(bio_err, BIO_printf(bio_err,
"didn't find starttls in server response," "Didn't find STARTTLS in server response,"
" trying anyway...\n"); " trying anyway...\n");
BIO_printf(sbio, "STARTTLS\r\n"); BIO_printf(sbio, "STARTTLS\r\n");
BIO_read(sbio, sbuf, BUFSIZZ); BIO_read(sbio, sbuf, BUFSIZZ);
@ -1958,6 +1959,7 @@ int s_client_main(int argc, char **argv)
{ {
int foundit = 0; int foundit = 0;
BIO *fbio = BIO_new(BIO_f_buffer()); BIO *fbio = BIO_new(BIO_f_buffer());
BIO_push(fbio, sbio); BIO_push(fbio, sbio);
BIO_gets(fbio, mbuf, BUFSIZZ); BIO_gets(fbio, mbuf, BUFSIZZ);
/* STARTTLS command requires CAPABILITY... */ /* STARTTLS command requires CAPABILITY... */
@ -1975,7 +1977,7 @@ int s_client_main(int argc, char **argv)
BIO_free(fbio); BIO_free(fbio);
if (!foundit) if (!foundit)
BIO_printf(bio_err, BIO_printf(bio_err,
"didn't find STARTTLS in server response," "Didn't find STARTTLS in server response,"
" trying anyway...\n"); " trying anyway...\n");
BIO_printf(sbio, ". STARTTLS\r\n"); BIO_printf(sbio, ". STARTTLS\r\n");
BIO_read(sbio, sbuf, BUFSIZZ); BIO_read(sbio, sbuf, BUFSIZZ);
@ -1984,6 +1986,7 @@ int s_client_main(int argc, char **argv)
case PROTO_FTP: case PROTO_FTP:
{ {
BIO *fbio = BIO_new(BIO_f_buffer()); BIO *fbio = BIO_new(BIO_f_buffer());
BIO_push(fbio, sbio); BIO_push(fbio, sbio);
/* wait for multi-line response to end from FTP */ /* wait for multi-line response to end from FTP */
do { do {
@ -2007,7 +2010,11 @@ int s_client_main(int argc, char **argv)
starttls_proto == PROTO_XMPP ? "client" : "server", starttls_proto == PROTO_XMPP ? "client" : "server",
xmpphost ? xmpphost : host); xmpphost ? xmpphost : host);
seen = BIO_read(sbio, mbuf, BUFSIZZ); seen = BIO_read(sbio, mbuf, BUFSIZZ);
mbuf[seen] = 0; if (seen < 0) {
BIO_printf(bio_err, "BIO_read failed\n");
goto end;
}
mbuf[seen] = '\0';
while (!strstr while (!strstr
(mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'") (mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'")
&& !strstr(mbuf, && !strstr(mbuf,
@ -2018,15 +2025,19 @@ int s_client_main(int argc, char **argv)
if (seen <= 0) if (seen <= 0)
goto shut; goto shut;
mbuf[seen] = 0; mbuf[seen] = '\0';
} }
BIO_printf(sbio, BIO_printf(sbio,
"<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
seen = BIO_read(sbio, sbuf, BUFSIZZ); seen = BIO_read(sbio, sbuf, BUFSIZZ);
sbuf[seen] = 0; if (seen < 0) {
BIO_printf(bio_err, "BIO_read failed\n");
goto shut;
}
sbuf[seen] = '\0';
if (!strstr(sbuf, "<proceed")) if (!strstr(sbuf, "<proceed"))
goto shut; goto shut;
mbuf[0] = 0; mbuf[0] = '\0';
} }
break; break;
case PROTO_TELNET: case PROTO_TELNET:
@ -2210,6 +2221,54 @@ int s_client_main(int argc, char **argv)
BIO_read(sbio, sbuf, BUFSIZZ); BIO_read(sbio, sbuf, BUFSIZZ);
} }
break; break;
case PROTO_SIEVE:
{
int foundit = 0;
BIO *fbio = BIO_new(BIO_f_buffer());
BIO_push(fbio, sbio);
/* wait for multi-line response to end from Sieve */
do {
mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
/*
* According to RFC 5804 § 1.7, capability
* is case-insensitive, make it uppercase
*/
if (mbuf_len > 1 && mbuf[0] == '"') {
make_uppercase(mbuf);
if (strncmp(mbuf, "\"STARTTLS\"", 10) == 0)
foundit = 1;
}
} while (mbuf_len > 1 && mbuf[0] == '"');
(void)BIO_flush(fbio);
BIO_pop(fbio);
BIO_free(fbio);
if (!foundit)
BIO_printf(bio_err,
"Didn't find STARTTLS in server response,"
" trying anyway...\n");
BIO_printf(sbio, "STARTTLS\r\n");
mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ);
if (mbuf_len < 0) {
BIO_printf(bio_err, "BIO_read failed\n");
goto end;
} else if (mbuf_len < 2) {
BIO_printf(bio_err, "Server does not support STARTTLS.\n");
goto shut;
}
/*
* According to RFC 5804 § 2.2, response codes are case-
* insensitive, make it uppercase but preserve the response.
*/
mbuf[mbuf_len] = '\0';
strncpy(sbuf, mbuf, 2);
make_uppercase(sbuf);
if (strncmp(sbuf, "OK", 2) != 0) {
BIO_printf(bio_err, "STARTTLS not supported: %s", mbuf);
goto shut;
}
}
break;
} }
for (;;) { for (;;) {

View File

@ -437,7 +437,7 @@ command for more information.
send the protocol-specific message(s) to switch to TLS for communication. send the protocol-specific message(s) to switch to TLS for communication.
B<protocol> is a keyword for the intended protocol. Currently, the only B<protocol> is a keyword for the intended protocol. Currently, the only
supported keywords are "smtp", "pop3", "imap", "ftp", "xmpp", "xmpp-server", supported keywords are "smtp", "pop3", "imap", "ftp", "xmpp", "xmpp-server",
"irc", "postgres", "lmtp" and "nntp". "irc", "postgres", "lmtp", "nntp" and "sieve".
=item B<-xmpphost hostname> =item B<-xmpphost hostname>