/* * 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[]) { char *CApath=NULL,*CAfile=NULL; int badop=0; int bio_pair=0; int force=0; int tls1=0,ssl2=0,ssl3=0,ret=1; int client_auth=0; int server_auth=0,i; int app_verify=0; char *server_cert=TEST_SERVER_CERT; char *server_key=NULL; char *client_cert=TEST_CLIENT_CERT; char *client_key=NULL; SSL_CTX *s_ctx=NULL; SSL_CTX *c_ctx=NULL; SSL_METHOD *meth=NULL; SSL *c_ssl,*s_ssl; int number=1,reuse=0; long bytes=1L; #ifndef OPENSSL_NO_DH DH *dh; int dhe1024 = 0, dhe1024dsa = 0; #endif int no_dhe = 0; int print_time = 0; clock_t s_time = 0, c_time = 0; int comp = 0; COMP_METHOD *cm = NULL; verbose = 0; debug = 0; cipher = 0; bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); CRYPTO_set_locking_callback(lock_dbg_cb); /* enable memory leak checking unless explicitly disabled */ if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off")))) { CRYPTO_malloc_debug_init(); CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); } else { /* OPENSSL_DEBUG_MEMORY=off */ CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0); } CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); RAND_seed(rnd_seed, sizeof rnd_seed); bio_stdout=BIO_new_fp(stdout,BIO_NOCLOSE); argc--; argv++; while (argc >= 1) { if (strcmp(*argv,"-server_auth") == 0) server_auth=1; else if (strcmp(*argv,"-client_auth") == 0) client_auth=1; else if (strcmp(*argv,"-v") == 0) verbose=1; else if (strcmp(*argv,"-d") == 0) debug=1; else if (strcmp(*argv,"-reuse") == 0) reuse=1; else if (strcmp(*argv,"-dhe1024") == 0) { #ifndef OPENSSL_NO_DH dhe1024=1; #else fprintf(stderr,"ignoring -dhe1024, since I'm compiled without DH\n"); #endif } else if (strcmp(*argv,"-dhe1024dsa") == 0) { #ifndef OPENSSL_NO_DH dhe1024dsa=1; #else fprintf(stderr,"ignoring -dhe1024, since I'm compiled without DH\n"); #endif } else if (strcmp(*argv,"-no_dhe") == 0) no_dhe=1; else if (strcmp(*argv,"-ssl2") == 0) ssl2=1; else if (strcmp(*argv,"-tls1") == 0) tls1=1; else if (strcmp(*argv,"-ssl3") == 0) ssl3=1; else if (strncmp(*argv,"-num",4) == 0) { if (--argc < 1) goto bad; number= atoi(*(++argv)); if (number == 0) number=1; } else if (strcmp(*argv,"-bytes") == 0) { if (--argc < 1) goto bad; bytes= atol(*(++argv)); if (bytes == 0L) bytes=1L; i=strlen(argv[0]); if (argv[0][i-1] == 'k') bytes*=1024L; if (argv[0][i-1] == 'm') bytes*=1024L*1024L; } else if (strcmp(*argv,"-cert") == 0) { if (--argc < 1) goto bad; server_cert= *(++argv); } else if (strcmp(*argv,"-s_cert") == 0) { if (--argc < 1) goto bad; server_cert= *(++argv); } else if (strcmp(*argv,"-key") == 0) { if (--argc < 1) goto bad; server_key= *(++argv); } else if (strcmp(*argv,"-s_key") == 0) { if (--argc < 1) goto bad; server_key= *(++argv); } else if (strcmp(*argv,"-c_cert") == 0) { if (--argc < 1) goto bad; client_cert= *(++argv); } else if (strcmp(*argv,"-c_key") == 0) { if (--argc < 1) goto bad; client_key= *(++argv); } else if (strcmp(*argv,"-cipher") == 0) { if (--argc < 1) goto bad; cipher= *(++argv); } else if (strcmp(*argv,"-CApath") == 0) { if (--argc < 1) goto bad; CApath= *(++argv); } else if (strcmp(*argv,"-CAfile") == 0) { if (--argc < 1) goto bad; CAfile= *(++argv); } else if (strcmp(*argv,"-bio_pair") == 0) { bio_pair = 1; } else if (strcmp(*argv,"-f") == 0) { force = 1; } else if (strcmp(*argv,"-time") == 0) { print_time = 1; } else if (strcmp(*argv,"-zlib") == 0) { comp = COMP_ZLIB; } else if (strcmp(*argv,"-rle") == 0) { comp = COMP_RLE; } else if (strcmp(*argv,"-app_verify") == 0) { app_verify = 1; } else { fprintf(stderr,"unknown option %s\n",*argv); badop=1; break; } argc--; argv++; } if (badop) { bad: sv_usage(); goto end; } if (!ssl2 && !ssl3 && !tls1 && number > 1 && !reuse && !force) { fprintf(stderr, "This case cannot work. Use -f to perform " "the test anyway (and\n-d to see what happens), " "or add one of -ssl2, -ssl3, -tls1, -reuse\n" "to avoid protocol mismatch.\n"); EXIT(1); } if (print_time) { if (!bio_pair) { fprintf(stderr, "Using BIO pair (-bio_pair)\n"); bio_pair = 1; } if (number < 50 && !force) fprintf(stderr, "Warning: For accurate timings, use more connections (e.g. -num 1000)\n"); } /* if (cipher == NULL) cipher=getenv("SSL_CIPHER"); */ SSL_library_init(); SSL_load_error_strings(); if (comp == COMP_ZLIB) cm = COMP_zlib(); if (comp == COMP_RLE) cm = COMP_rle(); if (cm != NULL) { if (cm->type != NID_undef) SSL_COMP_add_compression_method(comp, cm); else { fprintf(stderr, "Warning: %s compression not supported\n", (comp == COMP_RLE ? "rle" : (comp == COMP_ZLIB ? "zlib" : "unknown"))); ERR_print_errors_fp(stderr); } } #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) if (ssl2) meth=SSLv2_method(); else if (tls1) meth=TLSv1_method(); else if (ssl3) meth=SSLv3_method(); else meth=SSLv23_method(); #else #ifdef OPENSSL_NO_SSL2 meth=SSLv3_method(); #else meth=SSLv2_method(); #endif #endif c_ctx=SSL_CTX_new(meth); s_ctx=SSL_CTX_new(meth); if ((c_ctx == NULL) || (s_ctx == NULL)) { ERR_print_errors(bio_err); goto end; } if (cipher != NULL) { SSL_CTX_set_cipher_list(c_ctx,cipher); SSL_CTX_set_cipher_list(s_ctx,cipher); } #ifndef OPENSSL_NO_DH if (!no_dhe) { if (dhe1024dsa) { /* use SSL_OP_SINGLE_DH_USE to avoid small subgroup attacks */ SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE); dh=get_dh1024dsa(); } else if (dhe1024) dh=get_dh1024(); else dh=get_dh512(); SSL_CTX_set_tmp_dh(s_ctx,dh); DH_free(dh); } #else (void)no_dhe; #endif #ifndef OPENSSL_NO_RSA SSL_CTX_set_tmp_rsa_callback(s_ctx,tmp_rsa_cb); #endif if (!SSL_CTX_use_certificate_file(s_ctx,server_cert,SSL_FILETYPE_PEM)) { ERR_print_errors(bio_err); } else if (!SSL_CTX_use_PrivateKey_file(s_ctx, (server_key?server_key:server_cert), SSL_FILETYPE_PEM)) { ERR_print_errors(bio_err); goto end; } if (client_auth) { SSL_CTX_use_certificate_file(c_ctx,client_cert, SSL_FILETYPE_PEM); SSL_CTX_use_PrivateKey_file(c_ctx, (client_key?client_key:client_cert), SSL_FILETYPE_PEM); } if ( (!SSL_CTX_load_verify_locations(s_ctx,CAfile,CApath)) || (!SSL_CTX_set_default_verify_paths(s_ctx)) || (!SSL_CTX_load_verify_locations(c_ctx,CAfile,CApath)) || (!SSL_CTX_set_default_verify_paths(c_ctx))) { /* fprintf(stderr,"SSL_load_verify_locations\n"); */ ERR_print_errors(bio_err); /* goto end; */ } if (client_auth) { BIO_printf(bio_err,"client authentication\n"); SSL_CTX_set_verify(s_ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verify_callback); if (app_verify) { SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, app_verify_arg); } } if (server_auth) { BIO_printf(bio_err,"server authentication\n"); SSL_CTX_set_verify(c_ctx,SSL_VERIFY_PEER, verify_callback); if (app_verify) { SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, app_verify_arg); } } { int session_id_context = 0; SSL_CTX_set_session_id_context(s_ctx, (void *)&session_id_context, sizeof session_id_context); } c_ssl=SSL_new(c_ctx); s_ssl=SSL_new(s_ctx); #ifndef OPENSSL_NO_KRB5 if (c_ssl && c_ssl->kssl_ctx) { char localhost[MAXHOSTNAMELEN+2]; if (gethostname(localhost, sizeof localhost-1) == 0) { localhost[sizeof localhost-1]='\0'; if(strlen(localhost) == sizeof localhost-1) { BIO_printf(bio_err,"localhost name too long\n"); goto end; } kssl_ctx_setstring(c_ssl->kssl_ctx, KSSL_SERVER, localhost); } } #endif /* OPENSSL_NO_KRB5 */ for (i=0; i<number; i++) { if (!reuse) SSL_set_session(c_ssl,NULL); if (bio_pair) ret=doit_biopair(s_ssl,c_ssl,bytes,&s_time,&c_time); else ret=doit(s_ssl,c_ssl,bytes); } if (!verbose) { print_details(c_ssl, ""); } if ((number > 1) || (bytes > 1L)) BIO_printf(bio_stdout, "%d handshakes of %ld bytes done\n",number,bytes); if (print_time) { #ifdef CLOCKS_PER_SEC /* "To determine the time in seconds, the value returned * by the clock function should be divided by the value * of the macro CLOCKS_PER_SEC." * -- ISO/IEC 9899 */ BIO_printf(bio_stdout, "Approximate total server time: %6.2f s\n" "Approximate total client time: %6.2f s\n", (double)s_time/CLOCKS_PER_SEC, (double)c_time/CLOCKS_PER_SEC); #else /* "`CLOCKS_PER_SEC' undeclared (first use this function)" * -- cc on NeXTstep/OpenStep */ BIO_printf(bio_stdout, "Approximate total server time: %6.2f units\n" "Approximate total client time: %6.2f units\n", (double)s_time, (double)c_time); #endif } SSL_free(s_ssl); SSL_free(c_ssl); end: if (s_ctx != NULL) SSL_CTX_free(s_ctx); if (c_ctx != NULL) SSL_CTX_free(c_ctx); if (bio_stdout != NULL) BIO_free(bio_stdout); #ifndef OPENSSL_NO_RSA free_tmp_rsa(); #endif #ifndef OPENSSL_NO_ENGINE ENGINE_cleanup(); #endif CRYPTO_cleanup_all_ex_data(); ERR_free_strings(); ERR_remove_state(0); EVP_cleanup(); CRYPTO_mem_leaks(bio_err); if (bio_err != NULL) BIO_free(bio_err); EXIT(ret); }