コード例 #1
0
ファイル: estserver.c プロジェクト: StephenWall/libest
/*
 * This is the main entry point into the example EST server.
 * This routine parses the command line options, reads in the
 * cert chains, creates an EST context, initializes the HTTP
 * layer (mongoose), and starts a simple TCP server to accept
 * incoming EST requests.
 */
int main (int argc, char **argv)
{
    char c;
    int i;

    X509 *x;
    EVP_PKEY * priv_key;
    BIO *certin;
    DH *dh;
    EST_ERROR rv;
    int sleep_delay = 0;
    int retry_period = 300;
    char vfile[255];
    int option_index = 0;
    pem_password_cb *priv_key_cb = NULL;

    static struct option long_options[] = {
        {"srp", 1, NULL, 0},
        {"enforce-csr", 0, NULL, 0},
        {"token", 1, 0, 0},
        {"keypass", 1, 0, 0},
        {"keypass_stdin", 1, 0, 0 },
        {"keypass_arg", 1, 0, 0 },
        {NULL, 0, NULL, 0}
    };

#ifdef WIN32
    InitializeCriticalSection(&enrollment_critical_section);
#endif

    /* Show usage if -h or --help options are specified */
    if ((argc == 1)
            || (argc == 2
                    && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")))) {
        show_usage_and_exit();
    }

    while ((c = getopt_long(argc, argv, "?fhbwnovr:c:k:m:p:d:lt6", long_options,
        &option_index)) != -1) {
        switch (c) {
        case 0:
#if 0
            printf("option %s", long_options[option_index].name);
            if (optarg) {
                printf(" with arg %s", optarg);
            }
            printf("\n");
#endif
            if (!strncmp(long_options[option_index].name, "srp",
                strlen("srp"))) {
                srp = 1;
                strncpy(vfile, optarg, 255);
            }
            if (!strncmp(long_options[option_index].name, "enforce-csr",
                strlen("enforce-csr"))) {
                enforce_csr = 1;
            }
            if (!strncmp(long_options[option_index].name, "token",
                strlen("token"))) {
                http_token_auth = 1;
                memset(valid_token_value, 0, MAX_AUTH_TOKEN_LEN + 1);
                strncpy(&(valid_token_value[0]), optarg, MAX_AUTH_TOKEN_LEN);
            }
            if (!strncmp(long_options[option_index].name,"keypass_stdin", strlen("keypass_stdin"))) {
                priv_key_cb = PEM_def_callback;
            }
            if (!strncmp(long_options[option_index].name,"keypass_arg", strlen("keypass_arg"))) {
                strncpy(priv_key_pwd, optarg, MAX_PWD_LEN);
                priv_key_cb = string_password_cb;
            }
            break;
        case 'm':
            manual_enroll = 1;
            retry_period = atoi(optarg);
            break;
        case 'h':
            http_digest_auth = 1;
            break;
        case 'b':
            http_basic_auth = 1;
            break;
        case 'w':
            write_csr = 1;
            break;
        case 'n':
            http_auth_disable = 1;
            break;
        case 'o':
            disable_forced_http_auth = 1;
            break;
        case 'v':
            verbose = 1;
            break;
        case 'l':
            crl = 1;
            break;
        case 't':
            pop = 1;
            break;
        case '6':
            v6 = 1;
            break;
#ifndef DISABLE_PTHREADS
        case 'd':
            sleep_delay = atoi(optarg);
            break;
#endif
        case 'p':
            tcp_port = atoi(optarg);
            break;
        case 'c':
            strncpy(certfile, optarg, EST_MAX_FILE_LEN);
            break;
        case 'k':
            strncpy(keyfile, optarg, EST_MAX_FILE_LEN);
            break;
        case 'r':
            if (strnlen(optarg, MAX_REALM_LEN+1) > MAX_REALM_LEN) {
                printf("\nRealm value is too large.  Max is 32 characters\n");
                exit(1);
            }
            
            strncpy(realm, optarg, MAX_REALM_LEN);
            break;
        case 'f':
            /* turn FIPS on if user requested it
             * and exit if failure.
             */
            set_fips_return = FIPS_mode_set(1);
            if (set_fips_return != 1) {
                set_fips_error = ERR_get_error();
                printf("\nERROR WHILE SETTING FIPS MODE ON exiting ....\n");
                exit(1);
            } else {
                printf("\nRunning EST Sample Server with FIPS MODE = ON !\n");
            }
            ;
            break;
        default:
            show_usage_and_exit();
            break;
        }
    }
    argc -= optind;
    argv += optind;

    if (verbose) {
        print_version(stdout);
    }

    if (getenv("EST_CSR_ATTR")) {
        printf("\nUsing CSR Attributes: %s", getenv("EST_CSR_ATTR"));
    }

    if (!getenv("EST_CACERTS_RESP")) {
        printf("\nEST_CACERTS_RESP file not set, set this env variable to resolve");
        exit(1);
    }
    if (!getenv("EST_TRUSTED_CERTS")) {
        printf("\nEST_TRUSTED_CERTS file not set, set this env variable to resolve");
        exit(1);
    }

    /*
     * Read in the CA certificates
     */
    cacerts_len = read_binary_file(getenv("EST_CACERTS_RESP"), &cacerts_raw);
    if (cacerts_len <= 0) {
        printf("\nEST_CACERTS_RESP file could not be read\n");
        exit(1);
    }
    /*
     * Read in the trusted CA certificates for the local TLS context
     */
    if (getenv("EST_TRUSTED_CERTS")) {
        trustcerts_len = read_binary_file(getenv("EST_TRUSTED_CERTS"),
            &trustcerts);
        if (trustcerts_len <= 0) {
            printf("\nEST_TRUSTED_CERTS file could not be read\n");
            exit(1);
        }
    }

    est_apps_startup();

    /*
     * Read in the local server certificate
     */
    certin = BIO_new(BIO_s_file_internal());
    if (BIO_read_filename(certin, certfile) <= 0) {
        printf("\nUnable to read server certificate file %s\n", certfile);
        exit(1);
    }
    /*
     * This reads the file, which is expected to be PEM encoded.  If you're using
     * DER encoded certs, you would invoke d2i_X509_bio() instead.
     */
    x = PEM_read_bio_X509(certin, NULL, NULL, NULL);
    if (x == NULL) {
        printf("\nError while reading PEM encoded server certificate file %s\n",
            certfile);
        exit(1);
    }
    BIO_free(certin);

    /*
     * Read in the server's private key
     */

    priv_key = read_private_key(keyfile, priv_key_cb);
    if (priv_key == NULL) {
        printf("\nError while reading PEM encoded server private key file %s\n",
            keyfile);
        ERR_print_errors_fp(stderr);
        exit(1);
    }

    bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
    if (!bio_err) {
        printf("\nBIO not working\n");
        exit(1);
    }

    if (verbose) {
        est_init_logger(EST_LOG_LVL_INFO, NULL);
        est_enable_backtrace(1);
    } else {
        est_init_logger(EST_LOG_LVL_ERR, NULL);
    }
    ectx = est_server_init(trustcerts, trustcerts_len, cacerts_raw, cacerts_len,
        EST_CERT_FORMAT_PEM, realm, x, priv_key);
    if (!ectx) {
        printf("\nUnable to initialize EST context.  Aborting!!!\n");
        exit(1);
    }
    est_set_ex_data(ectx, &test_app_data);

    if (enforce_csr) {
        est_server_enforce_csrattr(ectx);
    }

    /*
     * Change the retry-after period.  This is not
     * necessary, it's only shown here as an example.
     */
    if (verbose)
        printf("\nRetry period being set to: %d \n", retry_period);
    est_server_set_retry_period(ectx, retry_period);

    if (crl) {
        est_enable_crl(ectx);
    }
    if (!pop) {
        if (verbose)
            printf("\nDisabling PoP check");
        est_server_disable_pop(ectx);
    }

    if (srp) {
        srp_db = SRP_VBASE_new(NULL);
        if (!srp_db) {
            printf("\nUnable allocate SRP verifier database.  Aborting!!!\n");
            exit(1);
        }
        if (SRP_VBASE_init(srp_db, vfile) != SRP_NO_ERROR) {
            printf("\nUnable initialize SRP verifier database.  Aborting!!!\n");
            exit(1);
        }

        if (est_server_enable_srp(ectx, &process_ssl_srp_auth)) {
            printf("\nUnable to enable SRP.  Aborting!!!\n");
            exit(1);
        }
    }

    if (est_set_ca_enroll_cb(ectx, &process_pkcs10_enrollment)) {
        printf(
            "\nUnable to set EST pkcs10 enrollment callback.  Aborting!!!\n");
        exit(1);
    }
    /*
     * We use the same handler for re-enrollment.  Our little toy
     * CA doesn't do anything special for re-enrollment.  A real
     * CA would need to implement the requirements in section
     * 4.2 of the EST draft.
     */
    if (est_set_ca_reenroll_cb(ectx, &process_pkcs10_enrollment)) {
        printf(
            "\nUnable to set EST pkcs10 enrollment callback.  Aborting!!!\n");
        exit(1);
    }
    if (est_set_csr_cb(ectx, &process_csrattrs_request)) {
        printf("\nUnable to set EST CSR Attributes callback.  Aborting!!!\n");
        exit(1);
    }
    if (!http_auth_disable) {
        if (est_set_http_auth_cb(ectx, &process_http_auth)) {
            printf("\nUnable to set EST HTTP AUTH callback.  Aborting!!!\n");
            exit(1);
        }
    }
    if (disable_forced_http_auth) {
        if (verbose)
            printf(
                "\nDisabling HTTP authentication when TLS client auth succeeds\n");
        if (est_set_http_auth_required(ectx, HTTP_AUTH_NOT_REQUIRED)) {
            printf("\nUnable to disable required HTTP auth.  Aborting!!!\n");
            exit(1);
        }
    }

    if (http_digest_auth) {
        
        MD5_CTX c;
        int len;
        static unsigned char ha1_input_buf[32*3+2];
        unsigned char md[17];
        int i;
        
        rv = est_server_set_auth_mode(ectx, AUTH_DIGEST);
        if (rv != EST_ERR_NONE) {
            printf(
                "\nUnable to enable HTTP digest authentication.  Aborting!!!\n");
            exit(1);
        }

        /*
         * Cache away the realm value and build the HA1
         */
        strncpy(digest_user[1], realm, MAX_REALM_LEN);

        len = sprintf((char *)ha1_input_buf, "%s:%s:%s", "estuser", realm, "estpwd");
        MD5_Init(&c);
        MD5_Update(&c, ha1_input_buf, len);
        MD5_Final((unsigned char *)md, &c);

        printf("\nDigest HA1 value = ");
        memset(digest_user[2], 0, 32);
        for(i = 0; i < 16; i++){
            
            sprintf(&(digest_user[2][i*2]),"%.2x", (unsigned char) md[i]);
            printf("%c%c", digest_user[2][i*2], digest_user[2][i*2+1]);
        }
        printf("\n");
    }

    if (http_basic_auth) {
        rv = est_server_set_auth_mode(ectx, AUTH_BASIC);
        if (rv != EST_ERR_NONE) {
            printf(
                "\nUnable to enable HTTP basic authentication.  Aborting!!!\n");
            exit(1);
        }
    }

    if (http_token_auth) {
        rv = est_server_set_auth_mode(ectx, AUTH_TOKEN);
        if (rv != EST_ERR_NONE) {
            printf(
                "\nUnable to enable HTTP token authentication.  Aborting!!!\n");
            exit(1);
        }
    }

    /*
     * Set DH parameters for TLS
     */
    dh = get_dh1024dsa();
    if (dh) {
        est_server_set_dh_parms(ectx, dh);
    }
    DH_free(dh);

    /*
     * Install thread locking mechanism for OpenSSL
     */
    mutex_buf = malloc(CRYPTO_num_locks() * sizeof(MUTEX_TYPE));
    if (!mutex_buf) {
        printf("Cannot allocate mutexes");
        exit(1);
    }
    for (i = 0; i < CRYPTO_num_locks(); i++)
        MUTEX_SETUP(mutex_buf[i]);
    CRYPTO_set_id_callback(id_function);
    CRYPTO_set_locking_callback(locking_function);

    printf("\nLaunching EST server...\n");

    rv = est_server_start(ectx);
    if (rv != EST_ERR_NONE) {
        printf("\nFailed to init mg (rv=%d)\n", rv);
        exit(1);
    }

    /*
     * Start the simple server, which opens a TCP
     * socket, waits for incoming connections, and
     * invokes the EST handler for each connection.
     */
    start_simple_server(ectx, tcp_port, sleep_delay, v6);

    cleanup();
    EVP_PKEY_free(priv_key);
    X509_free(x);
    return 0;
}
コード例 #2
0
ファイル: us1864.c プロジェクト: DDvO/libest
/*
 * est_server_set_auth_mode() - unit test
 *
 * First, Test the parameters of est_server_set_auth_mode()
 */
static void us1864_test1 (void)
{
    unsigned char *cacerts = NULL;
    int cacerts_len = 0;    
    BIO *certin, *keyin;
    X509 *x;
    EVP_PKEY *priv_key;
    int rv;
    EST_CTX *ctx;
    EST_ERROR est_rv;

    LOG_FUNC_NM;
    
    /*
     * Read in the CA certificates
     */
    cacerts_len = read_binary_file(US1864_CACERT, &cacerts);
    CU_ASSERT(cacerts_len > 0);
    
    /*
     * Read the server cert
     */
    certin = BIO_new(BIO_s_file_internal());
    rv = BIO_read_filename(certin, US1864_SERVER_CERT); 
    CU_ASSERT(rv > 0);
    x = PEM_read_bio_X509(certin, NULL, NULL, NULL);
    CU_ASSERT(x != NULL);
    BIO_free(certin);

    /*
     * Read the server key 
     */
    keyin = BIO_new(BIO_s_file_internal());
    rv = BIO_read_filename(keyin, US1864_SERVER_KEY);
    CU_ASSERT(rv > 0);
    priv_key = PEM_read_bio_PrivateKey(keyin, NULL, NULL, NULL);
    CU_ASSERT(priv_key != NULL);
    BIO_free(keyin);

    /* 
     * init EST in server mode
     */
    est_init_logger(EST_LOG_LVL_INFO, NULL);
    ctx = est_server_init(cacerts, cacerts_len, 
                          cacerts, cacerts_len,
                          EST_CERT_FORMAT_PEM, "testrealm", x, priv_key);
                  
    CU_ASSERT(ctx != NULL);
    
    est_rv = est_server_set_auth_mode(ctx, AUTH_NONE);
    CU_ASSERT(est_rv == EST_ERR_BAD_MODE);
    est_rv = est_server_set_auth_mode(ctx, AUTH_BASIC);
    CU_ASSERT(est_rv == EST_ERR_NONE);
    est_rv = est_server_set_auth_mode(ctx, AUTH_DIGEST);
    CU_ASSERT(est_rv == EST_ERR_NONE);
    est_rv = est_server_set_auth_mode(ctx, AUTH_TOKEN);
    CU_ASSERT(est_rv == EST_ERR_NONE);
    est_rv = est_server_set_auth_mode(ctx, 0xffffffff);
    CU_ASSERT(est_rv == EST_ERR_BAD_MODE);

#if 0
    //TODO: FIPS mode is not a concern
    /*
     * Make sure we don't allow DIGEST mode when in FIPS mode
     */
    FIPS_mode_set(1);
    est_rv = est_server_set_auth_mode(ctx, AUTH_DIGEST);
    CU_ASSERT(est_rv == EST_ERR_BAD_MODE);
    FIPS_mode_set(0);    
#endif
        
    X509_free(x);
    EVP_PKEY_free(priv_key);

    est_destroy(ctx);
}
コード例 #3
0
ファイル: est_proxy.c プロジェクト: DDvO/libest
/*! @brief est_proxy_set_auth_mode() is used by an application layer to
    configure the HTTP authentication method to use for validating the
    identity of an EST client.
 
    @param ctx Pointer to the EST proxy context.  This was returned from
    est_proxy_init().
    @param amode Should be either AUTH_BASIC or AUTH_DIGEST

    This function can optionally be invoked by the application layer to change
    the default HTTP authentication mode.  The default mode is HTTP Basic
    authentication.  An application may desire to use Digest authentication
    instead, in which case this function can be used to set that mode.  This
    function should be invoked prior to starting the EST proxy.

    @return EST_ERROR.
 */
EST_ERROR est_proxy_set_auth_mode (EST_CTX *ctx, EST_HTTP_AUTH_MODE amode)
{
    return(est_server_set_auth_mode(ctx, amode));
}
コード例 #4
0
ファイル: estproxy.c プロジェクト: DDvO/libest
int main (int argc, char **argv)
{
    signed char c;
    EVP_PKEY *priv_key;
    BIO *certin, *keyin;
    X509 *x;
    EST_ERROR rv;
    int sleep_delay = 0;
    char vfile[255];
    int option_index = 0;
    static struct option long_options[] = {
        {"srp", 1, NULL, 0},
        {"token", 1, 0, 0},
        {"auth-token", 1, 0, 0},
        {"help", 0, NULL, 0},
        {NULL, 0, NULL, 0}
    };
    
    strncpy(est_server, "127.0.0.1", MAX_SERVER_LEN);

    while ((c = getopt_long(argc, argv, "?vt6nhfr:c:k:s:p:l:d:", long_options, &option_index)) != -1) {
        switch (c) {
	case 0:
            if (!strncmp(long_options[option_index].name,"srp", strlen("srp"))) {
		srp = 1;
                strncpy(vfile, optarg, 255);
            } else
            if (!strncmp(long_options[option_index].name,"token", strlen("token"))) {
		server_http_token_auth = 1;
                strncpy(&(valid_token_value[0]), optarg, MAX_AUTH_TOKEN_LEN);
            } else
            if (!strncmp(long_options[option_index].name,"auth-token", strlen("auth-token"))) {
                strncpy(est_auth_token, optarg, MAX_AUTH_TOKEN_LEN);
                client_token_auth_mode = 1;
            } else show_usage_and_exit();
	    break;
        case 'v':
            verbose = 1;
            break;
        case 't':
            pop = 1;
            break;
        case '6':
            v6 = 1;
            break;
        case 'h':
            http_digest_auth = 1;
            break;
        case 'b':
            http_basic_auth = 1;
            break;
        case 'n':
            http_auth_disable = 1;
            break;
        case 'c':
	    strncpy(certfile, optarg, EST_MAX_FILE_LEN);
            break;
        case 'k':
	    strncpy(keyfile, optarg, EST_MAX_FILE_LEN);
            break;
        case 'r':
	    strncpy(realm, optarg, MAX_REALM);
            break;
        case 's':
            strncpy(est_server, optarg, MAX_SERVER_LEN);
            break;
#ifndef DISABLE_PTHREADS
        case 'd':
	    sleep_delay = atoi(optarg);
            break;
#endif
        case 'p':
            est_server_port = atoi(optarg);
            break;
        case 'l':
            listen_port = atoi(optarg);
            break;
        case 'f':
           /*
            * Turn FIPS on if user requested it and exit if failure
            */
            set_fips_return = FIPS_mode_set(1);
            if (set_fips_return != 1) {
              set_fips_error = ERR_get_error();
              printf("\nERROR WHILE SETTING FIPS MODE ON exiting ....\n");
              exit(1);
            } else {
              printf("Running EST Sample Proxy with FIPS MODE = ON !\n");
            };
            break;
        case '?':
        default:
            show_usage_and_exit();
            break;
        }
    }
    argc -= optind;
    argv += optind;

    if (verbose) {
        fprintf(stdout, "EST Proxy start up values:\n");
        print_version(stdout);
	fprintf(stdout, "Using EST server %s:%d\n", est_server, est_server_port);
	fprintf(stdout, "Listening on port: %d\n", listen_port);
	fprintf(stdout, "Using identity cert file: %s\n", certfile);
	fprintf(stdout, "Using identity private key file: %s\n", keyfile);
	fprintf(stdout, "Using realm value: %s\n", realm);
        fflush(stdout);
    }

    if (!getenv("EST_TRUSTED_CERTS")) {
        printf("\nEST_TRUSTED_CERTS file not set, set this env variable to resolve\n");
        exit(1);
    }

    /*
     * Read in the CA certificates
     */
    if (getenv("EST_CACERTS_RESP")) {
        cacerts_len = read_binary_file(getenv("EST_CACERTS_RESP"), &cacerts_raw);
        if (cacerts_len <= 0) {
            printf("\nEST_CACERTS_RESP file could not be read\n");
            exit(1);
        }
    }
    /*
     * Read in the trusted CA certificates for the local TLS context
     */
    if (getenv("EST_TRUSTED_CERTS")) {
        trustcerts_len = read_binary_file(getenv("EST_TRUSTED_CERTS"), &trustcerts);
        if (trustcerts_len <= 0) {
            printf("\nEST_TRUSTED_CERTS file could not be read\n");
            exit(1);
        }
    }

    est_apps_startup();

    /*
     * Read in the local server certificate 
     */
    certin = BIO_new(BIO_s_file_internal());
    if (BIO_read_filename(certin, certfile) <= 0) {
	printf("\nUnable to read server certificate file %s\n", certfile);
	exit(1);
    }
    /*
     * This reads the file, which is expected to be PEM encoded.  If you're using 
     * DER encoded certs, you would invoke d2i_X509_bio() instead.
     */
    x = PEM_read_bio_X509(certin, NULL, NULL, NULL);
    if (x == NULL) {
	printf("\nError while reading PEM encoded server certificate file %s\n", certfile);
	exit(1);
    }
    BIO_free(certin);

    /* 
     * Read in the server's private key
     */
    keyin = BIO_new(BIO_s_file_internal());
    if (BIO_read_filename(keyin, keyfile) <= 0) {
	printf("\nUnable to read server private key file %s\n", keyfile);
	exit(1);
    }
    /*
     * This reads in the private key file, which is expected to be a PEM
     * encoded private key.  If using DER encoding, you would invoke
     * d2i_PrivateKey_bio() instead. 
     */
    priv_key = PEM_read_bio_PrivateKey(keyin, NULL, NULL, NULL);
    if (priv_key == NULL) {
	printf("\nError while reading PEM encoded private key file %s\n", keyfile);
	ERR_print_errors_fp(stderr);
	exit(1);
    }
    BIO_free(keyin);

    if (verbose) {
	est_init_logger(EST_LOG_LVL_INFO, NULL);
	est_enable_backtrace(1);
    }

    /*
     * Initialize EST context from libest
     */
    ectx = est_proxy_init(trustcerts, trustcerts_len,
                          cacerts_raw, cacerts_len, EST_CERT_FORMAT_PEM,
                          realm, x, priv_key, "estuser", "estpwd");
    if (!ectx) {
        printf("\nUnable to initialize EST context.  Aborting!!!\n");
        exit(1);
    }
    if (!http_auth_disable) {
	if (est_set_http_auth_cb(ectx, &process_http_auth)) {
	    printf("\nUnable to set EST HTTP AUTH callback.  Aborting!!!\n");
	    exit(1);
	}    
    }

    if (http_digest_auth) {
	rv = est_proxy_set_auth_mode(ectx, AUTH_DIGEST);
	if (rv != EST_ERR_NONE) {
            printf("\nUnable to enable HTTP digest authentication.  Aborting!!!\n");
            exit(1);
	}
    }

    if (http_basic_auth) {
	rv = est_server_set_auth_mode(ectx, AUTH_BASIC);
	if (rv != EST_ERR_NONE) {
            printf("\nUnable to enable HTTP basic authentication.  Aborting!!!\n");
            exit(1);
	}
    }
    
    if (server_http_token_auth) {
	rv = est_server_set_auth_mode(ectx, AUTH_TOKEN);
	if (rv != EST_ERR_NONE) {
            printf("\nUnable to enable HTTP token authentication.  Aborting!!!\n");
            exit(1);
	}
    }

    if (!pop) {
	printf("Disabling PoP check\n");
	est_server_disable_pop(ectx);
    }

    est_proxy_set_server(ectx, est_server, est_server_port);

    if (srp) {
	srp_db = SRP_VBASE_new(NULL);
	if (!srp_db) {
	    printf("\nUnable allocate SRP verifier database.  Aborting!!!\n");
	    exit(1); 
	}
	if (SRP_VBASE_init(srp_db, vfile) != SRP_NO_ERROR) {
	    printf("\nUnable initialize SRP verifier database.  Aborting!!!\n");
	    exit(1); 
	}
	
	if (est_server_enable_srp(ectx, &process_ssl_srp_auth)) { 
	    printf("\nUnable to enable SRP.  Aborting!!!\n");
	    exit(1);
	}
    }

    if (client_token_auth_mode) {
        rv = est_proxy_set_auth_cred_cb(ectx, auth_credentials_token_cb);
        if (rv != EST_ERR_NONE) {
            printf("\nUnable to register token auth callback.  Aborting!!!\n");
            exit(1);
        }        
    }            
    
#ifndef DISABLE_PTHREADS
    /*
     * Install thread locking mechanism for OpenSSL
     */
    int size = sizeof(pthread_mutex_t) * CRYPTO_num_locks();
    if ((ssl_mutexes = (pthread_mutex_t*)malloc((size_t)size)) == NULL) {
        printf("\nCannot allocate mutexes\n");
	exit(1);
    }   

    int i;
    for (i = 0; i < CRYPTO_num_locks(); i++) {
        pthread_mutex_init(&ssl_mutexes[i], NULL);
    }
    CRYPTO_set_locking_callback(&ssl_locking_callback);
    CRYPTO_set_id_callback(&ssl_id_callback);
#endif

    printf("Launching EST proxy...\n");

    rv = est_proxy_start(ectx);
    if (rv != EST_ERR_NONE) {
        printf("\nFailed to init mg (rv=%d)\n", rv);
        exit(1);
    }

    /*
     * Start the simple server, which opens a TCP
     * socket, waits for incoming connections, and
     * invokes the EST handler for each connection.
     */
    start_simple_server(ectx, listen_port, sleep_delay, v6);

    cleanup();
    return 0;
}