示例#1
0
void tlsFree(TlsContext *context)
{
   //Invalid TLS context?
   if(context == NULL)
      return;

   //Properly close the TLS session by sending a close notify
   tlsShutdown(context);

   //Release server name
   osFreeMem(context->serverName);

   //Free Diffie-Hellman context
   dhFree(&context->dhContext);
   //Free ECDH context
   ecdhFree(&context->ecdhContext);
   //Release peer's RSA public key
   rsaFreePublicKey(&context->peerRsaPublicKey);
   //Release peer's DSA public key
   dsaFreePublicKey(&context->peerDsaPublicKey);
   //Release peer's EC domain parameters
   ecFreeDomainParameters(&context->peerEcParams);
   //Release peer's EC public key
   ecFree(&context->peerEcPublicKey);

   //Release send buffer
   memset(context->txBuffer, 0, TLS_TX_BUFFER_SIZE);
   osFreeMem(context->txBuffer);

   //Release receive buffer
   memset(context->rxBuffer, 0, TLS_RX_BUFFER_SIZE);
   osFreeMem(context->rxBuffer);

   //Release resources used to compute handshake message hash
   osFreeMem(context->handshakeMd5Context);
   osFreeMem(context->handshakeSha1Context);
   osFreeMem(context->handshakeHashContext);

   //Release the write encryption context
   if(context->writeCipherContext)
   {
      //Clear context contents, then release memory
      memset(context->writeCipherContext, 0, context->cipherAlgo->contextSize);
      osFreeMem(context->writeCipherContext);
   }

   //Release the read encryption context
   if(context->readCipherContext)
   {
      //Clear context contents, then release memory
      memset(context->readCipherContext, 0, context->cipherAlgo->contextSize);
      osFreeMem(context->readCipherContext);
   }

   //Clear the TLS context before freeing memory
   memset(context, 0, sizeof(TlsContext));
   osFreeMem(context);
}
示例#2
0
文件: tls.c 项目: hyper123/CycloneTCP
void tlsFree(TlsContext *context)
{
   //Invalid TLS context?
   if(context == NULL)
      return;

   //Properly close the TLS session by sending a close notify
   tlsShutdown(context);

   //Release server name
   osMemFree(context->serverName);

   //Free multiple precision integers
   dhFreeParameters(&context->dhParameters);
   rsaFreePublicKey(&context->peerRsaPublicKey);
   dsaFreePublicKey(&context->peerDsaPublicKey);

   //Release send buffer
   memset(context->txBuffer, 0, TLS_TX_BUFFER_SIZE);
   osMemFree(context->txBuffer);

   //Release receive buffer
   memset(context->rxBuffer, 0, TLS_RX_BUFFER_SIZE);
   osMemFree(context->rxBuffer);

   //Release resources used to compute handshake message hash
   osMemFree(context->handshakeMd5Context);
   osMemFree(context->handshakeSha1Context);
   osMemFree(context->handshakeHashContext);

   //Release the write encryption context
   if(context->writeCipherContext)
   {
      //Clear context contents, then release memory
      memset(context->writeCipherContext, 0, context->cipherAlgo->contextSize);
      osMemFree(context->writeCipherContext);
   }

   //Release the read encryption context
   if(context->readCipherContext)
   {
      //Clear context contents, then release memory
      memset(context->readCipherContext, 0, context->cipherAlgo->contextSize);
      osMemFree(context->readCipherContext);
   }

   //Clear the TLS context before freeing memory
   memset(context, 0, sizeof(TlsContext));
   osMemFree(context);
}
void httpConnectionTask(void *param)
{
   error_t error;
   uint_t counter;
   HttpConnection *connection;

   //Point to the structure representing the HTTP connection
   connection = (HttpConnection *) param;

   //Endless loop
   while(1)
   {
      //Wait for an incoming connection attempt
      osWaitForEvent(&connection->startEvent, INFINITE_DELAY);

      //Initialize status code
      error = NO_ERROR;

#if (HTTP_SERVER_TLS_SUPPORT == ENABLED)
      //Use SSL/TLS to secure the connection?
      if(connection->settings->useTls)
      {
         //Debug message
         TRACE_INFO("Initializing SSL/TLS session...\r\n");

         //Start of exception handling block
         do
         {
            //Allocate SSL/TLS context
            connection->tlsContext = tlsInit();
            //Initialization failed?
            if(connection->tlsContext == NULL)
            {
               //Report an error
               error = ERROR_OUT_OF_MEMORY;
               //Exit immediately
               break;
            }

            //Select server operation mode
            error = tlsSetConnectionEnd(connection->tlsContext, TLS_CONNECTION_END_SERVER);
            //Any error to report?
            if(error) break;

            //Bind TLS to the relevant socket
            error = tlsSetSocket(connection->tlsContext, connection->socket);
            //Any error to report?
            if(error) break;

            //Invoke user-defined callback, if any
            if(connection->settings->tlsInitCallback != NULL)
            {
               //Perform SSL/TLS related initialization
               error = connection->settings->tlsInitCallback(connection, connection->tlsContext);
               //Any error to report?
               if(error) break;
            }

            //Establish a secure session
            error = tlsConnect(connection->tlsContext);
            //Any error to report?
            if(error) break;

            //End of exception handling block
         } while(0);
      }
      else
      {
         //Do not use SSL/TLS
         connection->tlsContext = NULL;
      }
#endif

      //Check status code
      if(!error)
      {
         //Process incoming requests
         for(counter = 0; counter < HTTP_SERVER_MAX_REQUESTS; counter++)
         {
            //Debug message
            TRACE_INFO("Waiting for request...\r\n");

            //Clear request header
            memset(&connection->request, 0, sizeof(HttpRequest));
            //Clear response header
            memset(&connection->response, 0, sizeof(HttpResponse));

            //Read the HTTP request header and parse its contents
            error = httpReadHeader(connection);
            //Any error to report?
            if(error)
            {
               //Debug message
               TRACE_INFO("No HTTP request received or parsing error...\r\n");
               break;
            }

#if (HTTP_SERVER_BASIC_AUTH_SUPPORT == ENABLED || HTTP_SERVER_DIGEST_AUTH_SUPPORT == ENABLED)
            //No Authorization header found?
            if(!connection->request.auth.found)
            {
               //Invoke user-defined callback, if any
               if(connection->settings->authCallback != NULL)
               {
                  //Check whether the access to the specified URI is authorized
                  connection->status = connection->settings->authCallback(connection,
                     connection->request.auth.user, connection->request.uri);
               }
               else
               {
                  //Access to the specified URI is allowed
                  connection->status = HTTP_ACCESS_ALLOWED;
               }
            }

            //Check access status
            if(connection->status == HTTP_ACCESS_ALLOWED)
            {
               //Access to the specified URI is allowed
               error = NO_ERROR;
            }
            else if(connection->status == HTTP_ACCESS_BASIC_AUTH_REQUIRED)
            {
               //Basic access authentication is required
               connection->response.auth.mode = HTTP_AUTH_MODE_BASIC;
               //Report an error
               error = ERROR_AUTH_REQUIRED;
            }
            else if(connection->status == HTTP_ACCESS_DIGEST_AUTH_REQUIRED)
            {
               //Digest access authentication is required
               connection->response.auth.mode = HTTP_AUTH_MODE_DIGEST;
               //Report an error
               error = ERROR_AUTH_REQUIRED;
            }
            else
            {
               //Access to the specified URI is denied
               error = ERROR_NOT_FOUND;
            }
#endif

            //Debug message
            TRACE_INFO("Sending HTTP response to the client...\r\n");

            //Check status code
            if(!error)
            {
               //Default HTTP header fields
               connection->response.version = connection->request.version;
               connection->response.noCache = FALSE;

#if (HTTP_SERVER_PERSISTENT_CONN_SUPPORT == ENABLED)
               //Persistent connections are accepted
               connection->response.keepAlive = connection->request.keepAlive;
#else
               //Connections are not persistent by default
               connection->response.keepAlive = FALSE;
#endif

#if (HTTP_SERVER_SSI_SUPPORT == ENABLED)
               //Use server-side scripting to dynamically generate HTML code?
               if(httpCompExtension(connection->request.uri, ".stm") ||
                  httpCompExtension(connection->request.uri, ".shtm") ||
                  httpCompExtension(connection->request.uri, ".shtml"))
               {
                  //SSI processing (Server Side Includes)
                  error = ssiExecuteScript(connection, connection->request.uri, 0);
               }
               else
#endif
               {
                  //Send the contents of the requested page
                  error = httpSendResponse(connection, connection->request.uri);
               }

               //The requested resource is not available?
               if(error == ERROR_NOT_FOUND)
               {
                  //Default HTTP header fields
                  connection->response.version = connection->request.version;
                  connection->response.statusCode = 200;
                  connection->response.keepAlive = connection->request.keepAlive;
                  connection->response.noCache = FALSE;
                  connection->response.location = NULL;
                  connection->response.contentType = mimeGetType(connection->request.uri);
                  connection->response.chunkedEncoding = TRUE;

                  //Invoke user-defined callback, if any
                  if(connection->settings->uriNotFoundCallback != NULL)
                  {
                     error = connection->settings->uriNotFoundCallback(connection,
                        connection->request.uri);
                  }
               }
            }

            //Bad request?
            if(error == ERROR_INVALID_REQUEST)
            {
               //Send an error 400 and close the connection immediately
               httpSendErrorResponse(connection, 400,
                  "The request is badly formed");
            }
            //Authorization required?
            else if(error == ERROR_AUTH_REQUIRED)
            {
               //Send an error 401 and keep the connection alive
               error = httpSendErrorResponse(connection, 401,
                  "Authorization required");
            }
            //Page not found?
            else if(error == ERROR_NOT_FOUND)
            {
               //Send an error 404 and keep the connection alive
               error = httpSendErrorResponse(connection, 404,
                  "The requested page could not be found");
            }

            //Internal error?
            if(error)
            {
               //Close the connection immediately
               break;
            }

            //Check whether the connection is persistent or not
            if(!connection->request.keepAlive || !connection->response.keepAlive)
            {
               //Close the connection immediately
               break;
            }
         }
      }

#if (HTTP_SERVER_TLS_SUPPORT == ENABLED)
      //Valid SSL/TLS context?
      if(connection->tlsContext != NULL)
      {
         //Debug message
         TRACE_INFO("Closing SSL/TLS session...\r\n");

         //Gracefully close SSL/TLS session
         tlsShutdown(connection->tlsContext);
         //Release context
         tlsFree(connection->tlsContext);
      }
#endif

      //Debug message
      TRACE_INFO("Graceful shutdown...\r\n");
      //Graceful shutdown
      socketShutdown(connection->socket, SOCKET_SD_BOTH);

      //Debug message
      TRACE_INFO("Closing socket...\r\n");
      //Close socket
      socketClose(connection->socket);

      //Ready to serve the next connection request...
      connection->running = FALSE;
      //Release semaphore
      osReleaseSemaphore(&connection->serverContext->semaphore);
   }
}