wfreerdp-server: fix server-side TLS on Windows
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Wed, 13 Jun 2012 03:09:30 +0000 (23:09 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Wed, 13 Jun 2012 03:09:30 +0000 (23:09 -0400)
include/freerdp/crypto/tls.h
libfreerdp-core/listener.c
libfreerdp-core/tcp.c
libfreerdp-crypto/nla.c
libfreerdp-crypto/tls.c
server/Windows/wfreerdp.c

index fa9f155..f0b2e89 100644 (file)
@@ -49,6 +49,7 @@ FREERDP_API boolean tls_disconnect(rdpTls* tls);
 FREERDP_API int tls_read(rdpTls* tls, uint8* data, int length);
 FREERDP_API int tls_write(rdpTls* tls, uint8* data, int length);
 
+FREERDP_API int tls_read_all(rdpTls* tls, uint8* data, int length);
 FREERDP_API int tls_write_all(rdpTls* tls, uint8* data, int length);
 
 FREERDP_API boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname);
index 42641f0..4d2f109 100644 (file)
@@ -190,12 +190,13 @@ static void freerdp_listener_close(freerdp_listener* instance)
 {
        int i;
 
-       rdpListener* listener = (rdpListener*)instance->listener;
+       rdpListener* listener = (rdpListener*) instance->listener;
 
        for (i = 0; i < listener->num_sockfds; i++)
        {
                close(listener->sockfds[i]);
        }
+
        listener->num_sockfds = 0;
 }
 
index 6c0390f..7a40175 100644 (file)
@@ -189,8 +189,14 @@ boolean tcp_set_blocking_mode(rdpTcp* tcp, boolean blocking)
        else
                fcntl(tcp->sockfd, F_SETFL, flags | O_NONBLOCK);
 #else
+       int status;
        u_long arg = blocking;
-       ioctlsocket(tcp->sockfd, FIONBIO, &arg);
+
+       status = ioctlsocket(tcp->sockfd, FIONBIO, &arg);
+
+       if (status != NO_ERROR)
+               printf("ioctlsocket() failed with error: %ld\n", status);
+
        tcp->wsa_event = WSACreateEvent();
        WSAEventSelect(tcp->sockfd, tcp->wsa_event, FD_READ);
 #endif
index f0a0d73..b3e1024 100644 (file)
@@ -342,7 +342,7 @@ int credssp_client_authenticate(rdpCredssp* credssp)
                        return -1;
 
 #ifdef WITH_DEBUG_CREDSSP
-               printf("Receiving Authentication Token\n");
+               printf("Receiving Authentication Token (%d)\n", credssp->negoToken.cbBuffer);
                winpr_HexDump(credssp->negoToken.pvBuffer, credssp->negoToken.cbBuffer);
 #endif
 
@@ -457,9 +457,9 @@ int credssp_server_authenticate(rdpCredssp* credssp)
        have_context = false;
        have_input_buffer = false;
        have_pub_key_auth = false;
-       memset(&input_buffer, 0, sizeof(SecBuffer));
-       memset(&output_buffer, 0, sizeof(SecBuffer));
-       memset(&credssp->ContextSizes, 0, sizeof(SecPkgContext_Sizes));
+       ZeroMemory(&input_buffer, sizeof(SecBuffer));
+       ZeroMemory(&output_buffer, sizeof(SecBuffer));
+       ZeroMemory(&credssp->ContextSizes, sizeof(SecPkgContext_Sizes));
 
        fContextReq = ASC_REQ_REPLAY_DETECT | ASC_REQ_SEQUENCE_DETECT |
                        ASC_REQ_CONFIDENTIALITY | ASC_REQ_DELEGATE;
@@ -490,6 +490,12 @@ int credssp_server_authenticate(rdpCredssp* credssp)
                p_buffer->pvBuffer = credssp->negoToken.pvBuffer;
                p_buffer->cbBuffer = credssp->negoToken.cbBuffer;
 
+               if (credssp->negoToken.cbBuffer < 1)
+               {
+                       printf("CredSSP: invalid negoToken!\n");
+                       return -1;
+               }
+
                output_buffer_desc.ulVersion = SECBUFFER_VERSION;
                output_buffer_desc.cBuffers = 1;
                output_buffer_desc.pBuffers = &output_buffer;
@@ -1060,12 +1066,13 @@ int credssp_recv(rdpCredssp* credssp)
        int status;
        UINT32 version;
 
-       s = stream_new(2048);
-       status = tls_read(credssp->tls, s->data, stream_get_left(s));
-       s->size = status;
+       s = stream_new(4096);
+
+       status = tls_read_all(credssp->tls, s->p, stream_get_left(s));
 
        if (status < 0)
        {
+               printf("credssp_recv() error: %d\n", status);
                stream_free(s);
                return -1;
        }
index 0df0f9a..beba56b 100644 (file)
@@ -115,7 +115,8 @@ boolean tls_connect(rdpTls* tls)
                return false;
        }
 
-       if (!tls_verify_certificate(tls, cert, tls->settings->hostname)) {
+       if (!tls_verify_certificate(tls, cert, tls->settings->hostname))
+       {
                printf("tls_connect: certificate not trusted, aborting.\n");
                tls_disconnect(tls);
                tls_free_certificate(cert);
@@ -187,12 +188,29 @@ boolean tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_fi
                return false;
        }
 
-       connection_status = SSL_accept(tls->ssl);
-
-       if (connection_status <= 0)
+       while (1)
        {
-               if (tls_print_error("SSL_accept", tls->ssl, connection_status))
-                       return false;
+               connection_status = SSL_accept(tls->ssl);
+
+               if (connection_status <= 0)
+               {
+                       switch (SSL_get_error(tls->ssl, connection_status))
+                       {
+                               case SSL_ERROR_WANT_READ:
+                               case SSL_ERROR_WANT_WRITE:
+                                       break;
+
+                               default:
+                                       if (tls_print_error("SSL_accept", tls->ssl, connection_status))
+                                               return false;
+                                       break;
+
+                       }
+               }
+               else
+               {
+                       break;
+               }
        }
 
        printf("TLS connection accepted\n");
@@ -231,6 +249,19 @@ int tls_read(rdpTls* tls, uint8* data, int length)
        return status;
 }
 
+int tls_read_all(rdpTls* tls, uint8* data, int length)
+{
+       int status;
+
+       do
+       {
+               status = tls_read(tls, data, length);
+       }
+       while (status == 0);
+
+       return status;
+}
+
 int tls_write(rdpTls* tls, uint8* data, int length)
 {
        int status;
@@ -297,11 +328,11 @@ boolean tls_print_error(char* func, SSL* connection, int value)
                        return true;
 
                case SSL_ERROR_WANT_READ:
-                       printf("SSL_ERROR_WANT_READ\n");
+                       printf("%s: SSL_ERROR_WANT_READ\n", func);
                        return false;
 
                case SSL_ERROR_WANT_WRITE:
-                       printf("SSL_ERROR_WANT_WRITE\n");
+                       printf("%s: SSL_ERROR_WANT_WRITE\n", func);
                        return false;
 
                case SSL_ERROR_SYSCALL:
index e8a2e9f..bd7c7b6 100644 (file)
@@ -167,7 +167,10 @@ static DWORD WINAPI wf_peer_main_loop(LPVOID lpParam)
        /* Initialize the real server settings here */
        client->settings->cert_file = xstrdup("server.crt");
        client->settings->privatekey_file = xstrdup("server.key");
+
        client->settings->nla_security = true;
+       client->settings->tls_security = false;
+       client->settings->rdp_security = false;
 
        client->PostConnect = wf_peer_post_connect;
        client->Activate = wf_peer_activate;
@@ -217,7 +220,7 @@ static void wf_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
                g_thread_count++;
 }
 
-static void test_server_main_loop(freerdp_listener* instance)
+static void wf_server_main_loop(freerdp_listener* instance)
 {
        int rcount;
        void* rfds[32];
@@ -267,7 +270,7 @@ int main(int argc, char* argv[])
        if (instance->Open(instance, NULL, port))
        {
                /* Entering the server main loop. In a real server the listener can be run in its own thread. */
-               test_server_main_loop(instance);
+               wf_server_main_loop(instance);
        }
 
        if (g_thread_count > 0)