make outgoing SSL_connect() non-blocking
[freeradius.git] / src / main / tls_listen.c
index 67db5d1..785b243 100644 (file)
@@ -33,6 +33,7 @@ USES_APPLE_DEPRECATED_API     /* OpenSSL API has been deprecated by Apple */
 #include <sys/stat.h>
 #endif
 
+#ifdef WITH_TCP
 #ifdef WITH_TLS
 #ifdef HAVE_OPENSSL_RAND_H
 #include <openssl/rand.h>
@@ -156,7 +157,6 @@ static int tls_socket_recv(rad_listen_t *listener)
                rad_assert(sock->packet != NULL);
                request->packet = talloc_steal(request, sock->packet);
 
-               request->component = "<core>";
                request->component = "<tls-connect>";
 
                request->reply = rad_alloc(request, false);
@@ -174,7 +174,7 @@ static int tls_socket_recv(rad_listen_t *listener)
 
                SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_REQUEST, (void *)request);
                SSL_set_ex_data(sock->ssn->ssl, fr_tls_ex_index_certs, (void *) &sock->certs);
-               SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_TALLOC, sock->parent);
+               SSL_set_ex_data(sock->ssn->ssl, FR_TLS_EX_INDEX_TALLOC, NULL);
 
                doing_init = true;
        }
@@ -287,7 +287,7 @@ static int tls_socket_recv(rad_listen_t *listener)
        PTHREAD_MUTEX_UNLOCK(&sock->mutex);
 
        if (!rad_packet_ok(packet, 0, NULL)) {
-               ERROR("Receive - %s", fr_strerror());
+               if (DEBUG_ENABLED) ERROR("Receive - %s", fr_strerror());
                DEBUG("Closing TLS socket from client");
                PTHREAD_MUTEX_LOCK(&sock->mutex);
                tls_socket_close(listener);
@@ -437,6 +437,11 @@ int dual_tls_send(rad_listen_t *listener, REQUEST *request)
                return 0;
        }
 
+       if (request->reply->data_len > (MAX_PACKET_LEN - 100)) {
+               RWARN("Packet is large, and possibly truncated - %zd vs max %d",
+                     request->reply->data_len, MAX_PACKET_LEN);
+       }
+
        /*
         *      Sign the packet.
         */
@@ -474,6 +479,34 @@ int dual_tls_send(rad_listen_t *listener, REQUEST *request)
        return 0;
 }
 
+static int try_connect(tls_session_t *ssn)
+{
+       int ret;
+       ret = SSL_connect(ssn->ssl);
+       if (ret < 0) {
+               switch (SSL_get_error(ssn->ssl, ret)) {
+                       default:
+                               break;
+
+
+
+               case SSL_ERROR_WANT_READ:
+               case SSL_ERROR_WANT_WRITE:
+                       ssn->connected = false;
+                       return 0;
+               }
+       }
+
+       if (ret <= 0) {
+               tls_error_io_log(NULL, ssn, ret, "Failed in " STRINGIFY(__FUNCTION__) " (SSL_connect)");
+               talloc_free(ssn);
+
+               return -1;
+       }
+
+       return 1;
+}
+
 
 #ifdef WITH_PROXY
 /*
@@ -495,6 +528,18 @@ static ssize_t proxy_tls_read(rad_listen_t *listener)
        uint8_t *data;
        listen_socket_t *sock = listener->data;
 
+       if (!sock->ssn->connected) {
+               rcode = try_connect(sock->ssn);
+               if (rcode == 0) return 0;
+
+               if (rcode < 0) {
+                       SSL_shutdown(sock->ssn->ssl);
+                       return -1;
+               }
+
+               sock->ssn->connected = true;
+       }
+
        /*
         *      Get the maximum size of data to receive.
         */
@@ -522,10 +567,7 @@ static ssize_t proxy_tls_read(rad_listen_t *listener)
                                return -1;
 
                        default:
-                               while ((err = ERR_get_error())) {
-                                       DEBUG("proxy recv says %s",
-                                             ERR_error_string(err, NULL));
-                               }
+                               tls_error_log(NULL, "Failed in proxy receive");
 
                                goto do_close;
                        }
@@ -691,6 +733,20 @@ int proxy_tls_send(rad_listen_t *listener, REQUEST *request)
                                                request);
        }
 
+       if (!sock->ssn->connected) {
+               PTHREAD_MUTEX_LOCK(&sock->mutex);
+               rcode = try_connect(sock->ssn);
+               PTHREAD_MUTEX_LOCK(&sock->mutex);
+               if (rcode == 0) return 0;
+
+               if (rcode < 0) {
+                       SSL_shutdown(sock->ssn->ssl);
+                       return -1;
+               }
+
+               sock->ssn->connected = true;
+       }
+
        DEBUG3("Proxy is writing %u bytes to SSL",
               (unsigned int) request->proxy->data_len);
        PTHREAD_MUTEX_LOCK(&sock->mutex);
@@ -707,8 +763,7 @@ int proxy_tls_send(rad_listen_t *listener, REQUEST *request)
                        break;  /* let someone else retry */
 
                default:
-                       DEBUG("proxy SSL_write says %s",
-                             ERR_error_string(err, NULL));
+                       tls_error_log(NULL, "Failed in proxy send");
                        DEBUG("Closing TLS socket to home server");
                        tls_socket_close(listener);
                        PTHREAD_MUTEX_UNLOCK(&sock->mutex);
@@ -722,3 +777,4 @@ int proxy_tls_send(rad_listen_t *listener, REQUEST *request)
 #endif /* WITH_PROXY */
 
 #endif /* WITH_TLS */
+#endif /* WITH_TCP */