/* * 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; }
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; }