]> diplodocus.org Git - nmh/blobdiff - sbr/netsec.c
Move m_getfld's MS_* mbox-type macros to the only user.
[nmh] / sbr / netsec.c
index 79fd6a0ddcb2fe7c53823027771bf5bc1d3b87c4..ab05cf8e85e9235c6f874169bc0b488b40a36ec0 100644 (file)
@@ -1,6 +1,4 @@
-
-/*
- * netsec.c -- Network security routines for handling protocols that
+/* netsec.c -- Network security routines for handling protocols that
  *            require SASL and/or TLS.
  *
  * This code is Copyright (c) 2016, by the authors of nmh.  See the
@@ -56,6 +54,7 @@ static SSL_CTX *sslctx = NULL;                /* SSL Context */
 struct _netsec_context {
     int ns_readfd;             /* Read descriptor for network connection */
     int ns_writefd;            /* Write descriptor for network connection */
+    int ns_noclose;            /* Do not close file descriptors if set */
     int ns_snoop;              /* If true, display network data */
     int ns_snoop_noend;                /* If true, didn't get a CR/LF on last line */
     netsec_snoop_callback *ns_snoop_cb; /* Snoop output callback */
@@ -142,6 +141,7 @@ netsec_init(void)
     NEW(nsc);
     nsc->ns_readfd = -1;
     nsc->ns_writefd = -1;
+    nsc->ns_noclose = 0;
     nsc->ns_snoop = 0;
     nsc->ns_snoop_noend = 0;
     nsc->ns_snoop_cb = NULL;
@@ -182,11 +182,10 @@ netsec_init(void)
 
 /*
  * Shutdown the connection completely and free all resources.
- * The connection is only closed if the flag is given.
  */
 
 void
-netsec_shutdown(netsec_context *nsc, int closeflag)
+netsec_shutdown(netsec_context *nsc)
 {
     mh_xfree(nsc->ns_userid);
     mh_xfree(nsc->ns_hostname);
@@ -220,7 +219,7 @@ netsec_shutdown(netsec_context *nsc, int closeflag)
        BIO_free_all(nsc->ssl_io);
 #endif /* TLS_SUPPORT */
 
-    if (closeflag) {
+    if (! nsc->ns_noclose) {
        if (nsc->ns_readfd != -1)
            close(nsc->ns_readfd);
        if (nsc->ns_writefd != -1 && nsc->ns_writefd != nsc->ns_readfd)
@@ -393,7 +392,7 @@ netsec_read(netsec_context *nsc, void *buffer, size_t size, char **errstr)
      * assume here that this has something in it.
      */
 
-    retlen = size > nsc->ns_inbuflen ? nsc->ns_inbuflen : size;
+    retlen = min(size, nsc->ns_inbuflen);
 
     memcpy(buffer, nsc->ns_inptr, retlen);
 
@@ -1011,14 +1010,13 @@ netsec_set_sasl_params(netsec_context *nsc, const char *service,
     nsc->sasl_creds = nmh_get_credentials(nsc->ns_hostname, nsc->ns_userid);
 
 #else /* CYRUS_SASL */
-    NMH_UNUSED(hostname);
     NMH_UNUSED(service);
     NMH_UNUSED(errstr);
 #endif /* CYRUS_SASL */
 
     /*
      * According to the RFC, mechanisms can only be uppercase letter, numbers,
-     * and a hypen or underscore.  So make sure we uppercase any letters
+     * and a hyphen or underscore.  So make sure we uppercase any letters
      * in case the user passed in lowercase.
      */
 
@@ -1438,7 +1436,7 @@ netsec_set_tls(netsec_context *nsc, int tls, int noverify, char **errstr)
 #ifdef TLS_SUPPORT
     if (tls) {
        SSL *ssl;
-       BIO *rbio, *wbio, *ssl_bio;;
+        BIO *rbio, *wbio, *ssl_bio;
 
        if (! tls_initialized) {
            SSL_library_init();
@@ -1510,7 +1508,7 @@ netsec_set_tls(netsec_context *nsc, int tls, int noverify, char **errstr)
         * SSL BIO -> socket BIO.
         */
 
-       rbio = BIO_new_socket(nsc->ns_readfd, BIO_NOCLOSE);
+       rbio = BIO_new_socket(nsc->ns_readfd, BIO_CLOSE);
 
        if (! rbio) {
            netsec_err(errstr, "Unable to create a read socket BIO: %s",
@@ -1519,7 +1517,7 @@ netsec_set_tls(netsec_context *nsc, int tls, int noverify, char **errstr)
            return NOTOK;
        }
 
-       wbio = BIO_new_socket(nsc->ns_writefd, BIO_NOCLOSE);
+       wbio = BIO_new_socket(nsc->ns_writefd, BIO_CLOSE);
 
        if (! wbio) {
            netsec_err(errstr, "Unable to create a write socket BIO: %s",
@@ -1543,7 +1541,9 @@ netsec_set_tls(netsec_context *nsc, int tls, int noverify, char **errstr)
         */
 
        if (! noverify) {
+#ifdef HAVE_X509_VERIFY_PARAM_SET1_HOST
            X509_VERIFY_PARAM *param;
+#endif /* HAVE_X509_VERIFY_PARAM_SET1_HOST */
 
            SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
            if (! nsc->ns_hostname) {
@@ -1553,6 +1553,7 @@ netsec_set_tls(netsec_context *nsc, int tls, int noverify, char **errstr)
                return NOTOK;
            }
 
+#ifdef HAVE_X509_VERIFY_PARAM_SET1_HOST
            param = SSL_get0_param(ssl);
 
            if (! X509_VERIFY_PARAM_set1_host(param, nsc->ns_hostname, 0)) {
@@ -1562,6 +1563,7 @@ netsec_set_tls(netsec_context *nsc, int tls, int noverify, char **errstr)
                SSL_free(ssl);
                return NOTOK;
            }
+#endif /* HAVE_X509_VERIFY_PARAM_SET1_HOST */
        }
 
        ssl_bio = BIO_new(BIO_f_ssl());
@@ -1576,6 +1578,13 @@ netsec_set_tls(netsec_context *nsc, int tls, int noverify, char **errstr)
        BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE);
        nsc->ssl_io = ssl_bio;
 
+       /*
+        * Since SSL now owns these file descriptors, have it handle the
+        * closing of them instead of netsec_shutdown().
+        */
+
+       nsc->ns_noclose = 1;
+
        return OK;
     }
     BIO_free_all(nsc->ssl_io);
@@ -1583,6 +1592,7 @@ netsec_set_tls(netsec_context *nsc, int tls, int noverify, char **errstr)
 
 #else /* TLS_SUPPORT */
     NMH_UNUSED(nsc);
+    NMH_UNUSED(noverify);
 
     if (tls) {
        netsec_err(errstr, "TLS is not supported");
@@ -1621,7 +1631,7 @@ netsec_negotiate_tls(netsec_context *nsc, char **errstr)
            if (BIO_get_ssl(nsc->ssl_io, &ssl) < 1) {
                netsec_err(errstr, "Certificate verification failed, but "
                           "cannot retrieve SSL handle: %s",
-                          ERR_error_string(ERR_get_error(), NULL));
+                           ERR_error_string(errcode, NULL));
            } else {
                netsec_err(errstr, "Server certificate verification failed: %s",
                           X509_verify_cert_error_string(
@@ -1629,7 +1639,7 @@ netsec_negotiate_tls(netsec_context *nsc, char **errstr)
            }
        } else {
            netsec_err(errstr, "TLS negotiation failed: %s",
-                      ERR_error_string(ERR_get_error(), NULL));
+                       ERR_error_string(errcode, NULL));
        }
 
        /*