]> diplodocus.org Git - nmh/blobdiff - sbr/netsec.c
Remove X.400 address parsing
[nmh] / sbr / netsec.c
index 0fb4126294612ad77757f7aef6395d3343f1a221..2d70b37947c2392541c2c38dcc0f23d4d4524989 100644 (file)
@@ -6,10 +6,13 @@
  * complete copyright information.
  */
 
  * complete copyright information.
  */
 
-#include <h/mh.h>
-#include <h/utils.h>
-#include <h/netsec.h>
-#include <h/oauth.h>
+#include "h/mh.h"
+#include "credentials.h"
+#include "getcpy.h"
+#include "brkstring.h"
+#include "h/utils.h"
+#include "h/netsec.h"
+#include "h/oauth.h"
 #include <stdarg.h>
 #include <sys/select.h>
 #include "base64.h"
 #include <stdarg.h>
 #include <sys/select.h>
 #include "base64.h"
@@ -320,7 +323,7 @@ netsec_b64_snoop_decoder(netsec_context *nsc, const char *string, size_t len,
        len -= offset;
     }
 
        len -= offset;
     }
 
-    if (decodeBase64(string, &decoded, &decodedlen, 1, NULL) == OK) {
+    if (decodeBase64(string, &decoded, &decodedlen, 1) == OK) {
        /*
         * Some mechanisms produce large binary tokens, which aren't really
         * readable.  So let's do a simple heuristic.  If the token is greater
        /*
         * Some mechanisms produce large binary tokens, which aren't really
         * readable.  So let's do a simple heuristic.  If the token is greater
@@ -834,7 +837,7 @@ retry:
             * At that point, just give up.
             */
            netsec_err(errstr, "Internal error: wanted to printf() a total of "
             * At that point, just give up.
             */
            netsec_err(errstr, "Internal error: wanted to printf() a total of "
-                      "%d bytes, but our buffer size was only %d bytes",
+                      "%d bytes, but our buffer size was only %d bytes",
                       rc, nsc->ns_outbufsize);
            return NOTOK;
        }
                       rc, nsc->ns_outbufsize);
            return NOTOK;
        }
@@ -923,7 +926,7 @@ netsec_flush(netsec_context *nsc, char **errstr)
                if (nsc->ns_snoop_savebuf) {
                    cb_len += strlen(nsc->ns_snoop_savebuf);
                    nsc->ns_snoop_savebuf = mh_xrealloc(nsc->ns_snoop_savebuf,
                if (nsc->ns_snoop_savebuf) {
                    cb_len += strlen(nsc->ns_snoop_savebuf);
                    nsc->ns_snoop_savebuf = mh_xrealloc(nsc->ns_snoop_savebuf,
-                                               outlen);
+                                                       outlen);
                    ptr = nsc->ns_snoop_savebuf;
                } else {
                    ptr = snoopoutbuf;
                    ptr = nsc->ns_snoop_savebuf;
                } else {
                    ptr = snoopoutbuf;
@@ -1188,6 +1191,22 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr)
     int rc;
 #endif /* CYRUS_SASL || OAUTH_SUPPORT */
 
     int rc;
 #endif /* CYRUS_SASL || OAUTH_SUPPORT */
 
+    /*
+     * Output some SASL information if snoop is turned on
+     */
+
+    if (nsc->ns_snoop) {
+       fprintf(stderr, "SASL mechanisms supported by server: %s\n", mechlist);
+
+       if (nsc->sasl_mech) {
+               fprintf(stderr, "User has requested SASL mechanism: %s\n",
+                       nsc->sasl_mech);
+       } else {
+               fprintf(stderr, "No SASL mech selected, will pick "
+                       "the best mech supported by SASL library\n");
+       }
+    }
+
     /*
      * If we've been passed a requested mechanism, check our mechanism
      * list from the protocol.  If it's not supported, return an error.
     /*
      * If we've been passed a requested mechanism, check our mechanism
      * list from the protocol.  If it's not supported, return an error.
@@ -1226,6 +1245,10 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr)
         * error message.
         */
 
         * error message.
         */
 
+       if (nsc->ns_snoop) {
+               fprintf(stderr, "Using internal XOAUTH2 mechanism\n");
+       }
+
        if (! nsc->oauth_service) {
            netsec_err(errstr, "Internal error: OAuth2 service name not given");
            return NOTOK;
        if (! nsc->oauth_service) {
            netsec_err(errstr, "Internal error: OAuth2 service name not given");
            return NOTOK;
@@ -1237,7 +1260,7 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr)
                               &xoauth_client_res, &xoauth_client_res_len,
                               nsc->ns_snoop ? stderr : NULL) != OK) {
            netsec_err(errstr, "Internal error: Unable to get OAuth2 "
                               &xoauth_client_res, &xoauth_client_res_len,
                               nsc->ns_snoop ? stderr : NULL) != OK) {
            netsec_err(errstr, "Internal error: Unable to get OAuth2 "
-                      "bearer token");
+                      "bearer token");
            return NOTOK;
        }
 
            return NOTOK;
        }
 
@@ -1288,6 +1311,21 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr)
      * messages.
      */
 
      * messages.
      */
 
+    if (nsc->ns_snoop) {
+       const char *client_mechlist;
+
+       rc = sasl_listmech(nsc->sasl_conn, NULL, NULL, " ", NULL,
+                          &client_mechlist, NULL, NULL);
+
+       if (rc != SASL_OK) {
+               fprintf(stderr, "Unable to get client mechlist: %s\n",
+                       sasl_errstring(rc, NULL, NULL));
+       } else {
+               fprintf(stderr, "Client supported SASL mechanisms: %s\n",
+                       client_mechlist);
+       }
+    }
+
     ZERO(&secprops);
     secprops.maxbufsize = SASL_MAXRECVBUF;
 
     ZERO(&secprops);
     secprops.maxbufsize = SASL_MAXRECVBUF;
 
@@ -1301,6 +1339,12 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr)
 #endif /* TLS_SUPPORT */
                UINT_MAX;
 
 #endif /* TLS_SUPPORT */
                UINT_MAX;
 
+#ifdef TLS_SUPPORT
+    if (nsc->ns_snoop && nsc->tls_active)
+       fprintf(stderr, "SASL security layers disabled due to the use "
+               "of TLS\n");
+#endif /* TLS_SUPPORT */
+
     rc = sasl_setprop(nsc->sasl_conn, SASL_SEC_PROPS, &secprops);
 
     if (rc != SASL_OK) {
     rc = sasl_setprop(nsc->sasl_conn, SASL_SEC_PROPS, &secprops);
 
     if (rc != SASL_OK) {
@@ -1315,7 +1359,7 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr)
      */
 
     rc = sasl_client_start(nsc->sasl_conn,
      */
 
     rc = sasl_client_start(nsc->sasl_conn,
-                          nsc->sasl_mech ? nsc->sasl_mech : mechlist, NULL,
+                          nsc->sasl_mech ? nsc->sasl_mech : mechlist, NULL,
                           (const char **) &saslbuf, &saslbuflen,
                           &chosen_mech);
 
                           (const char **) &saslbuf, &saslbuflen,
                           &chosen_mech);
 
@@ -1327,6 +1371,9 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr)
 
     nsc->sasl_chosen_mech = getcpy(chosen_mech);
 
 
     nsc->sasl_chosen_mech = getcpy(chosen_mech);
 
+    if (nsc->ns_snoop)
+       fprintf(stderr, "Chosen sasl mechanism: %s\n", chosen_mech);
+
     if (nsc->sasl_proto_cb(NETSEC_SASL_START, saslbuf, saslbuflen, NULL, 0,
                           nsc->sasl_proto_context, errstr) != OK)
        return NOTOK;
     if (nsc->sasl_proto_cb(NETSEC_SASL_START, saslbuf, saslbuflen, NULL, 0,
                           nsc->sasl_proto_context, errstr) != OK)
        return NOTOK;
@@ -1336,7 +1383,7 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr)
      */
 
     while (rc == SASL_CONTINUE) {
      */
 
     while (rc == SASL_CONTINUE) {
-       /*
+       /*
         * Call our SASL callback, which will handle the details of
         * reading data from the network.
         */
         * Call our SASL callback, which will handle the details of
         * reading data from the network.
         */
@@ -1401,6 +1448,10 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr)
     nsc->sasl_ssf = *ssf;
 
     if (nsc->sasl_ssf > 0) {
     nsc->sasl_ssf = *ssf;
 
     if (nsc->sasl_ssf > 0) {
+       if (nsc->ns_snoop)
+           fprintf(stderr, "SASL security layer negotiated, SASL will "
+                   "perform encryption\n");
+
        rc = sasl_getprop(nsc->sasl_conn, SASL_MAXOUTBUF,
                          (const void **) &outbufmax);
 
        rc = sasl_getprop(nsc->sasl_conn, SASL_MAXOUTBUF,
                          (const void **) &outbufmax);
 
@@ -1453,6 +1504,15 @@ netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr)
        }
 
        nsc->sasl_seclayer = 1;
        }
 
        nsc->sasl_seclayer = 1;
+    } else if (nsc->ns_snoop) {
+       fprintf(stderr, "SASL Security layer NOT negotiated, SASL will NOT "
+               "perform encryption\n");
+#ifdef TLS_SUPPORT
+       if (nsc->tls_active) {
+           fprintf(stderr, "Encryption will be handled by TLS\n");
+       } else
+#endif /* TLS_SUPPORT */
+           fprintf(stderr, "Connection will NOT be encrypted, use caution\n");
     }
 
     return OK;
     }
 
     return OK;
@@ -1494,6 +1554,7 @@ netsec_get_sasl_ssf(netsec_context *nsc)
 #ifdef CYRUS_SASL
     return nsc->sasl_ssf;
 #else /* CYRUS_SASL */
 #ifdef CYRUS_SASL
     return nsc->sasl_ssf;
 #else /* CYRUS_SASL */
+    NMH_UNUSED(nsc);
     return 0;
 #endif /* CYRUS_SASL */
 }
     return 0;
 #endif /* CYRUS_SASL */
 }
@@ -1563,6 +1624,11 @@ netsec_set_tls(netsec_context *nsc, int tls, int noverify, char **errstr)
            return NOTOK;
        }
 
            return NOTOK;
        }
 
+       if (!nsc->ns_hostname) {
+           netsec_err(errstr, "Internal error: hostname not set");
+           return NOTOK;
+       }
+
        /*
         * Create the SSL structure which holds the data for a single
         * TLS connection.
        /*
         * Create the SSL structure which holds the data for a single
         * TLS connection.
@@ -1619,6 +1685,12 @@ netsec_set_tls(netsec_context *nsc, int tls, int noverify, char **errstr)
        SSL_set_bio(ssl, rbio, wbio);
        SSL_set_connect_state(ssl);
 
        SSL_set_bio(ssl, rbio, wbio);
        SSL_set_connect_state(ssl);
 
+       /*
+        * Use the hostname to set the Server Name Indicator extension
+        */
+
+       SSL_set_tlsext_host_name(ssl, nsc->ns_hostname);
+
        /*
         * If noverify is NOT set, then do certificate validation.
         * Turning on SSL_VERIFY_PEER will verify the certificate chain
        /*
         * If noverify is NOT set, then do certificate validation.
         * Turning on SSL_VERIFY_PEER will verify the certificate chain
@@ -1635,12 +1707,6 @@ netsec_set_tls(netsec_context *nsc, int tls, int noverify, char **errstr)
 #endif /* HAVE_X509_VERIFY_PARAM_SET1_HOST */
 
            SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
 #endif /* HAVE_X509_VERIFY_PARAM_SET1_HOST */
 
            SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
-           if (! nsc->ns_hostname) {
-               netsec_err(errstr, "Internal error: hostname not set and "
-                          "certification verification enabled");
-               SSL_free(ssl);
-               return NOTOK;
-           }
 
 #ifdef HAVE_X509_VERIFY_PARAM_SET1_HOST
            param = SSL_get0_param(ssl);
 
 #ifdef HAVE_X509_VERIFY_PARAM_SET1_HOST
            param = SSL_get0_param(ssl);
@@ -1659,7 +1725,7 @@ netsec_set_tls(netsec_context *nsc, int tls, int noverify, char **errstr)
 
        if (! ssl_bio) {
            netsec_err(errstr, "Unable to create a SSL BIO: %s",
 
        if (! ssl_bio) {
            netsec_err(errstr, "Unable to create a SSL BIO: %s",
-                      ERR_error_string(ERR_get_error(), NULL));
+                      ERR_error_string(ERR_get_error(), NULL));
            SSL_free(ssl);
            return NOTOK;
        }
            SSL_free(ssl);
            return NOTOK;
        }
@@ -1784,7 +1850,7 @@ netsec_err(char **errstr, const char *fmt, ...)
     int rc = 127;
 
     if (! errstr)
     int rc = 127;
 
     if (! errstr)
-       return;
+       return;
 
     do {
        errbufsize = rc + 1;
 
     do {
        errbufsize = rc + 1;