Sunday, April 13, 2025

Below is a step-by-step plan and sample code changes to add SSL to simple web server while keeping the design simple.

Step-by-Step Plan:

  1. Use OpenSSL. Install and link with the OpenSSL libraries.
  2. Initialize the OpenSSL library and create an SSL_CTX for the server (for example, using TLS_server_method()).
  3. Load your certificate and private key files.
  4. When accepting a new connection, wrap the socket with an SSL object and perform an SSL_accept before reading/writing data.
  5. Clean up the SSL_CTX when shutting down the server.

Below are sample code modifications.

Modify server.c to include OpenSSL headers and create initialization/cleanup functions:

Then, in your connection acceptance code (likely in a function handling new client connections), wrap the accepted socket with SSL:

Finally, in your main function, call InitializeSSL before opening the server and CleanupSSL during shutdown:

This approach keeps the design simple by integrating SSL initialization, connection wrapping, and cleanup into your current server code structure. Adjust the certificate and key file paths as needed.












Generate a self-signed certificate and key using OpenSSL. In your Terminal run:



openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days 365 \
-subj "/C=US/ST=State/L=City/O=Organization/OU=Unit/CN=localhost"



This command creates a 2048-bit RSA key and a certificate valid for 365 days. The certificate will use "localhost" as the Common Name.Optionally, combine the certificate and key into a .p12 file (if needed):

openssl pkcs12 -export -inkey key.pem -in cert.pem -out cert.p12 -name "LocalTestCert"



You'll be prompted to set an export password.

Add the certificate to your Mac System Keychain:Open Keychain Access (from /Applications/Utilities/).
Drag and drop “cert.pem” into the “System” keychain (or “login” if preferred).
Double-click the certificate, expand “Trust,” and select “Always Trust” for when using this certificate.
Close and input your password if prompted.


Restart Brave Browser. Brave uses the system's trust store, so it should now trust your self-signed certificate when accessing your test server over HTTPS on "localhost".




To add a self-signed OpenSSL certificate for a web browser on macOS, you need to first generate the certificate, then import it into Keychain Access, and finally, configure Keychain Access to trust the certificate. 
Here's a step-by-step guide:
1. Generate the Self-Signed Certificate:
  • OpenSSL Command: Use the following OpenSSL command in the Terminal to generate a self-signed certificate:
Code
openssl req -x509 -newkey rsa:2048 -keyout localhost.key -out localhost.pem -subj "/CN=localhost" -days 365
  • Explanation:
    • openssl req: Invokes the OpenSSL request tool.
    • -x509: Specifies that this is an X.509 certificate.
    • -newkey rsa:2048: Generates a new 2048-bit RSA key.
    • -keyout localhost.key: Specifies the output file for the private key.
    • -out localhost.pem: Specifies the output file for the self-signed certificate.
    • -subj "/CN=localhost": Sets the Subject (Common Name) to "localhost". You can change this to your actual domain name if needed.
    • -days 365: Sets the certificate validity to 365 days.
  • Key File: The private key (localhost.key) is crucial and should be kept secure. 
2. Import the Certificate into Keychain Access:
  • Open Keychain Access:
    Launch the Keychain Access application (Applications > Utilities > Keychain Access).
  • Select System Keychain:
    Choose "System" from the Keychains list on the left side.
  • Import Certificate:
    • Choose "File" > "Import Items...".
    • Navigate to the localhost.pem file and select it.
    • Click "Open".
  • Add to System Keychain:
    You'll be prompted to add the certificate to the System keychain. Confirm and choose "Add". 
3. Configure Trust in Keychain Access:
  • Locate the Certificate:
    In Keychain Access, navigate to the "Certificates" category and find the localhost certificate (or the name you assigned it).
  • Open Certificate Info:
    Double-click the certificate to open its details.
  • Change Trust Setting:
    Expand the "Trust" section and change the "When using this certificate" option to "Always Trust".
  • Save Changes:
    Close the certificate details window. You may be prompted for your password to save the changes. 
4. Test in your Browser:
  • Restart Browser: Close and reopen your web browser (Chrome, Safari, Firefox, etc.).
  • Access your Localhost: Navigate to your localhost server (e.g., https://localhost).
  • Verify Certificate: The browser should now trust the self-signed certificate and display a secure padlock icon in the address bar. 


#include <openssl/ssl.h>
#include <sys/socket.h>
#include <linux/tls.h>




// Assumed external globals and helper functions (MUST BE IMPLEMENTED ELSEWHERE)
SSL_CTX *ssl_ctx;
void store_ssl_state(int fd, SSL *ssl, int ktls_tx_active, int ktls_rx_active);
int extract_tls_crypto(SSL *ssl, int is_tx, struct tls_crypto_info *crypto_info);
void remove_connection_state(int fd); // For cleanup on failure, though not explicitly called here
ConnectionState* get_connection_state(int fd);
void remove_connection_state(int fd);





void NewConn(int client_fd) {
    SSL *ssl = NULL;
    int ktls_tx_active = 0;
    int ktls_rx_active = 0;
    int handshake_ok = 0;
    int crypto_extracted_tx = 0;
    int crypto_extracted_rx = 0;

    ssl = SSL_new(ssl_ctx);
    if (!ssl) return;

    if (SSL_set_fd(ssl, client_fd) != 1) {
        SSL_free(ssl);
        return;
    }

    if (SSL_accept(ssl) == 1) {
        handshake_ok = 1;
    } else {
        SSL_free(ssl);
        return;
    }

    if (handshake_ok) {
        struct tls_crypto_info crypto_info_tx;
        crypto_extracted_tx = extract_tls_crypto_info_for_ktls(ssl, 1 , &crypto_info_tx);
        if (crypto_extracted_tx) {
            if (setsockopt(client_fd, SOL_TLS, TLS_TX, &crypto_info_tx, sizeof(crypto_info_tx)) == 0) {
                ktls_tx_active = 1;
            }
        }

        struct tls_crypto_info crypto_info_rx;
        crypto_extracted_rx = extract_tls_crypto_info_for_ktls(ssl, 0 , &crypto_info_rx);
        if (crypto_extracted_rx) {
            if (setsockopt(client_fd, SOL_TLS, TLS_RX, &crypto_info_rx, sizeof(crypto_info_rx)) == 0) {
                ktls_rx_active = 1;
            }
        }

            // --- Create and Populate State Structure ---
    new_state = (ConnectionState*)malloc(sizeof(ConnectionState));
    if (!new_state) goto cleanup_error; // Failed to allocate state struct

    new_state->fd = client_fd;
    new_state->ssl_handle = ssl; // Assign the created handle
    new_state->ktls_tx_active = ktls_tx_active;
    new_state->ktls_rx_active = ktls_rx_active;

    // --- Store the State Structure ---
    if (!store_ssl_state(client_fd, new_state)) {
        // Failed to store (e.g., fd out of range in store function)
        free(new_state); // Free the struct we just allocated
        new_state = NULL; // Prevent use in cleanup
        goto cleanup_error; // Clean up SSL handle and close fd
    }

    // --- Success ---
    // State created and stored. Add fd to epoll etc. happens elsewhere.
    return;
    }
}


void ConnClose(int fd) {
    ConnectionState *state = get_connection_state(fd);



    if (state != NULL && state->ssl_handle != NULL) {
        SSL_shutdown(state->ssl_handle);
        SSL_free(state->ssl_handle);
    }

    remove_connection_state(fd);
}



No comments:

Post a Comment