#include "lib_acl.h" #if defined(ACL_MS_WINDOWS) #pragma comment(lib,"ws2_32") #pragma comment(lib, "wsock32") #endif #include #include "tls.h" #include "tls_params.h" #ifdef ACL_UNIX #include #endif #include static char *conf_file = "tlssvr.cf"; static char serv_addr[64]; int var_cfg_server_tls_loglevel; int var_server_tls_ccert_vd; int var_cfg_server_tls_scache_timeout; int var_server_tls_set_sessid; int var_server_enforce_tls; int var_server_ask_client_cert; int var_server_tls_req_ccert; int var_server_starttls_tmout; char *var_server_tls_cert_file; char *var_server_tls_key_file; char *var_server_tls_dcert_file; char *var_server_tls_dkey_file; char *var_server_tls_eccert_file; char *var_server_tls_eckey_file; char *var_server_tls_CAfile; char *var_server_tls_CApath; char *var_server_tls_dh1024_param_file; char *var_server_tls_dh512_param_file; char *var_server_tls_eecdh; char *var_server_tls_fpt_dgst; static ACL_CONFIG_INT_TABLE int_table[] = { { "server_tls_loglevel", 0, &var_cfg_server_tls_loglevel, 0, 0 }, { "server_tls_ccert_vd", 9, &var_server_tls_ccert_vd, 0, 0 }, { "server_tls_scache_timeout", 10, &var_cfg_server_tls_scache_timeout, 0, 0 }, { "server_tls_set_sessid", 1, &var_server_tls_set_sessid, 0, 0 }, { "server_enforce_tls", 1, &var_server_enforce_tls, 0, 0 }, { "server_ask_client_cert", 1, &var_server_ask_client_cert, 0, 0 }, { "server_tls_req_ccert", 1, &var_server_tls_req_ccert, 0, 0 }, { "server_starttls_tmout", 300, &var_server_starttls_tmout, 0, 0 }, { 0, 0, 0, 0, 0 }, }; static ACL_CONFIG_STR_TABLE str_table[] = { { "server_tls_cert_file", "conf/server.pem", &var_server_tls_cert_file }, { "server_tls_key_file", "conf/server.pem", &var_server_tls_key_file }, { "server_tls_dcert_file", "", &var_server_tls_dcert_file }, { "server_tls_dkey_file", "", &var_server_tls_dkey_file }, { "server_tls_eccert_file", "", &var_server_tls_eccert_file }, { "server_tls_eckey_file", "", &var_server_tls_eckey_file }, { "server_tls_CAfile", "conf/server.pem", &var_server_tls_CAfile }, { "server_tls_CApath", "", &var_server_tls_CApath }, { "server_tls_dh1024_param_file", "", &var_server_tls_dh1024_param_file }, { "server_tls_dh512_param_file", "", &var_server_tls_dh512_param_file }, { "server_tls_eecdh", "", &var_server_tls_eecdh }, { "server_tls_fpt_dgst", "sha1", &var_server_tls_fpt_dgst }, { 0, 0, 0 }, }; static TLS_SERVER_INIT_PROPS init_props; static void init(void) { acl_app_conf_load(conf_file); acl_get_app_conf_str_table(str_table); acl_get_app_conf_int_table(int_table); var_tlsmgr_stand_alone = 0; tls_server_init(); TLS_SERVER_SETUP(&init_props, log_level = var_cfg_server_tls_loglevel, verifydepth = var_server_tls_ccert_vd, cache_type = TLS_MGR_SCACHE_SERVER, scache_timeout = var_cfg_server_tls_scache_timeout, set_sessid = var_server_tls_set_sessid, cert_file = var_server_tls_cert_file, key_file = var_server_tls_key_file, dcert_file = var_server_tls_dcert_file, dkey_file = var_server_tls_dkey_file, eccert_file = var_server_tls_eccert_file, eckey_file = var_server_tls_eckey_file, CAfile = var_server_tls_CAfile, CApath = var_server_tls_CApath, dh1024_param_file = var_server_tls_dh1024_param_file, dh512_param_file = var_server_tls_dh512_param_file, eecdh_grade = var_server_tls_eecdh, protocols = var_server_enforce_tls ? var_server_tls_mand_proto : var_server_tls_proto, ask_ccert = var_server_ask_client_cert, fpt_dgst = var_server_tls_fpt_dgst); } static void usage(const char *procname) { printf("usage: %s -h [help] -c conf_file\n", procname); } static char *reply = "HTTP/1.1 200 OK\r\n" "Date: Thu, 09 Jul 2009 03:30:09 GMT\r\n" "Server: Apache/1.3.37 (Unix)\r\n" "Last-Modified: Fri, 13 Mar 2009 07:37:22 GMT\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" "\r\n" "hello world!"; static void free_ctx_fn(void *ctx) { TLS_APPL_STATE *server_tls_ctx = (TLS_APPL_STATE*) ctx; tls_free_app_context(server_tls_ctx); } static void client_thread(void *arg) { ACL_VSTREAM *client = (ACL_VSTREAM*) arg; static __thread TLS_APPL_STATE *server_tls_ctx; TLS_SESS_STATE *server_sess_ctx; TLS_SERVER_START_PROPS tls_props; char buf[4096]; int ret, i; time_t last, now; int tls_level = 2; char *namaddrport = "test.com"; char *serverid = "service:addr:port:helo"; char *tls_grade = "low"; /* high, medium, low, export, null */ char *tls_exclusions = ""; acl_tcp_nodelay(ACL_VSTREAM_SOCK(client), 1); if (server_tls_ctx == NULL) { server_tls_ctx = tls_server_create(&init_props); if (server_tls_ctx == NULL) { printf("tls_server_create error\n"); return; } acl_pthread_atexit_add(server_tls_ctx, free_ctx_fn); } server_sess_ctx = TLS_SERVER_START(&tls_props, ctx = server_tls_ctx, stream = client, log_level = var_server_tls_loglevel, timeout = var_server_starttls_tmout, requirecert = (var_server_tls_req_ccert && var_server_enforce_tls), serverid = serverid, namaddr = namaddrport, cipher_grade = tls_grade, cipher_exclusions = tls_exclusions, fpt_dgst = var_server_tls_fpt_dgst); if (server_sess_ctx == NULL) { printf("TLS_SERVER_START error\n"); acl_vstream_close(client); return; } if (tls_level >= TLS_LEV_VERIFY) { if (!TLS_CERT_IS_TRUSTED(server_sess_ctx)) { printf("Server certificate not trusted\n"); } } if (tls_level > TLS_LEV_ENCRYPT) { if (!TLS_CERT_IS_MATCHED(server_sess_ctx)) { printf("Server certificate not verified\n"); } } i = 0; time(&last); while (0) { ret = acl_vstream_gets(client, buf, sizeof(buf)); if (ret == ACL_VSTREAM_EOF) goto END; if (acl_vstream_writen(client, buf, ret) == ACL_VSTREAM_EOF) goto END; break; i++; if (i % 50000 == 0) { time(&now); printf("i: %d, time: %ld\n", i, now - last); last = now; } } while (1) { while (1) { ret = acl_vstream_gets_nonl(client, buf, sizeof(buf)); if (ret == ACL_VSTREAM_EOF) goto END; if (ret == 0) break; /* printf("buf: %s, ret: %d\n", buf, ret); */ } ret = acl_vstream_writen(client, reply, strlen(reply)); /* printf("\nret: %d, reply: \n%s\n", ret, reply); */ break; } END: tls_server_stop(server_tls_ctx, client, var_server_starttls_tmout, 0, server_sess_ctx); acl_vstream_close(client); } static void run(void) { ACL_VSTREAM *server, *client; acl_pthread_pool_t *pool; server = acl_vstream_listen(serv_addr, 128); if (server == NULL) { printf("listen %s error(%s)\n", serv_addr, acl_last_serror()); return; } pool = acl_thread_pool_create(10, 0); if (pool == NULL) { acl_vstream_close(server); printf("create thread pool error(%s)\n", acl_last_serror()); return; } while (1) { client = acl_vstream_accept(server, NULL, 0); if (client == NULL) { if (errno != ACL_EINTR) { printf("accept error(%s)\n", acl_last_serror()); break; } continue; } acl_pthread_pool_add(pool, client_thread, client); } acl_vstream_close(server); acl_pthread_pool_destroy(pool); } static void free_fn(void) { acl_myfree(conf_file); } int main(int argc, char *argv[]) { char ch; acl_init(); ACL_SAFE_STRNCPY(serv_addr, "0.0.0.0:443", sizeof(serv_addr)); while ((ch = getopt(argc, argv, "hc:")) > 0) { switch (ch) { case 'h': usage(argv[0]); exit (0); case 'c': conf_file = acl_mystrdup(optarg); atexit(free_fn); break; default: break; } } init(); run(); acl_end(); return (0); }