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); }
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); } }