Add Sieve support (RFC 5804) to s_client ("-starttls sieve")
authorRobert Scheck <robert@fedoraproject.org>
Thu, 9 Feb 2017 21:20:59 +0000 (22:20 +0100)
committerRich Salz <rsalz@openssl.org>
Tue, 14 Feb 2017 19:15:28 +0000 (14:15 -0500)
Reviewed-by: Andy Polyakov <appro@openssl.org>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2300)

apps/apps.c
apps/apps.h
apps/ca.c
apps/s_client.c
doc/man1/s_client.pod

index 969b6b84ed6ad4a2e2caf6075559e33aa967cbc6..216bc797df5287c9cae26548e68fc7785148c3a8 100644 (file)
@@ -2664,3 +2664,11 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
     }
     return 1;
 }
+
+void make_uppercase(char *string)
+{
+    int i;
+
+    for (i = 0; string[i] != '\0'; i++)
+        string[i] = toupper((unsigned char)string[i]);
+}
index 5bf8c1dfa28b784d377fbf2374c2367761b62b06..e7c860f1b4e6d826965a398d01d198e25da147c8 100644 (file)
@@ -559,6 +559,8 @@ int raw_write_stdout(const void *, int);
 # define TM_STOP         1
 double app_tminterval(int stop, int usertime);
 
+void make_uppercase(char *string);
+
 typedef struct verify_options_st {
     int depth;
     int quiet;
index 030f8b1d3d6e9bbfd80c700854e862c998c5d366..8329884612751f1ad73dd21cb6835788aeb9c8b9 100644 (file)
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -2141,8 +2141,7 @@ static int get_certificate_status(const char *serial, CA_DB *db)
     }
 
     /* Make it Upper Case */
-    for (i = 0; row[DB_serial][i] != '\0'; i++)
-        row[DB_serial][i] = toupper((unsigned char)row[DB_serial][i]);
+    make_uppercase(row[DB_serial]);
 
     ok = 1;
 
index ad237c3252fee6c263c320c5f855e8f1d18ccd35..6d960128f572715221ab054d0403259d4fcd33a3 100644 (file)
@@ -749,7 +749,8 @@ typedef enum PROTOCOL_choice {
     PROTO_IRC,
     PROTO_POSTGRES,
     PROTO_LMTP,
-    PROTO_NNTP
+    PROTO_NNTP,
+    PROTO_SIEVE
 } PROTOCOL_CHOICE;
 
 static const OPT_PAIR services[] = {
@@ -764,6 +765,7 @@ static const OPT_PAIR services[] = {
     {"postgres", PROTO_POSTGRES},
     {"lmtp", PROTO_LMTP},
     {"nntp", PROTO_NNTP},
+    {"sieve", PROTO_SIEVE},
     {NULL, 0}
 };
 
@@ -1911,12 +1913,12 @@ int s_client_main(int argc, char **argv)
              */
             int foundit = 0;
             BIO *fbio = BIO_new(BIO_f_buffer());
+
             BIO_push(fbio, sbio);
             /* Wait for multi-line response to end from LMTP or SMTP */
             do {
                 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)
                 BIO_printf(fbio, "LHLO %s\r\n", ehlo);
             else
@@ -1930,14 +1932,13 @@ int s_client_main(int argc, char **argv)
                 mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
                 if (strstr(mbuf, "STARTTLS"))
                     foundit = 1;
-            }
-            while (mbuf_len > 3 && mbuf[3] == '-');
+            } while (mbuf_len > 3 && mbuf[3] == '-');
             (void)BIO_flush(fbio);
             BIO_pop(fbio);
             BIO_free(fbio);
             if (!foundit)
                 BIO_printf(bio_err,
-                           "didn't find starttls in server response,"
+                           "Didn't find STARTTLS in server response,"
                            " trying anyway...\n");
             BIO_printf(sbio, "STARTTLS\r\n");
             BIO_read(sbio, sbuf, BUFSIZZ);
@@ -1958,6 +1959,7 @@ int s_client_main(int argc, char **argv)
         {
             int foundit = 0;
             BIO *fbio = BIO_new(BIO_f_buffer());
+
             BIO_push(fbio, sbio);
             BIO_gets(fbio, mbuf, BUFSIZZ);
             /* STARTTLS command requires CAPABILITY... */
@@ -1975,7 +1977,7 @@ int s_client_main(int argc, char **argv)
             BIO_free(fbio);
             if (!foundit)
                 BIO_printf(bio_err,
-                           "didn't find STARTTLS in server response,"
+                           "Didn't find STARTTLS in server response,"
                            " trying anyway...\n");
             BIO_printf(sbio, ". STARTTLS\r\n");
             BIO_read(sbio, sbuf, BUFSIZZ);
@@ -1984,6 +1986,7 @@ int s_client_main(int argc, char **argv)
     case PROTO_FTP:
         {
             BIO *fbio = BIO_new(BIO_f_buffer());
+
             BIO_push(fbio, sbio);
             /* wait for multi-line response to end from FTP */
             do {
@@ -2007,7 +2010,11 @@ int s_client_main(int argc, char **argv)
                        starttls_proto == PROTO_XMPP ? "client" : "server",
                        xmpphost ? xmpphost : host);
             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
                    (mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'")
                    && !strstr(mbuf,
@@ -2018,15 +2025,19 @@ int s_client_main(int argc, char **argv)
                 if (seen <= 0)
                     goto shut;
 
-                mbuf[seen] = 0;
+                mbuf[seen] = '\0';
             }
             BIO_printf(sbio,
                        "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
             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"))
                 goto shut;
-            mbuf[0] = 0;
+            mbuf[0] = '\0';
         }
         break;
     case PROTO_TELNET:
@@ -2210,6 +2221,54 @@ int s_client_main(int argc, char **argv)
             BIO_read(sbio, sbuf, BUFSIZZ);
         }
         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 (;;) {
index f8c4a9bb045418207b4dc2600cea754d0265a0d1..c4da79fda494da6603b08f6467be88cce6b0d49f 100644 (file)
@@ -437,7 +437,7 @@ command for more information.
 send the protocol-specific message(s) to switch to TLS for communication.
 B<protocol> is a keyword for the intended protocol.  Currently, the only
 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>