diff --git a/qse/cmd/http/httpd.c b/qse/cmd/http/httpd.c index 2a85cfa8..d81c99bb 100644 --- a/qse/cmd/http/httpd.c +++ b/qse/cmd/http/httpd.c @@ -179,6 +179,8 @@ enum SCFG_AUTH, SCFG_DIRCSS, SCFG_ERRCSS, + SCFG_SSLCERTFILE, + SCFG_SSLKEYFILE, SCFG_MAX }; @@ -241,6 +243,7 @@ struct server_xtn_t int num; qse_nwad_t bind; + int secure; qse_httpd_serverstd_makersrc_t orgmakersrc; qse_httpd_serverstd_freersrc_t orgfreersrc; @@ -250,6 +253,12 @@ struct server_xtn_t int root_is_nwad; qse_nwad_t root_nwad; + struct + { + qse_mchar_t* certfile; + qse_mchar_t* keyfile; + } ssl; + struct { qse_size_t count; @@ -571,6 +580,16 @@ static int query_server ( } return 0; } + + case QSE_HTTPD_SERVERSTD_SSL: + { + qse_httpd_serverstd_ssl_t* ssl; + ssl = (qse_httpd_serverstd_ssl_t*)result; + ssl->certfile = server_xtn->scfg[SCFG_SSLCERTFILE]; + ssl->keyfile = server_xtn->scfg[SCFG_SSLKEYFILE]; + return 0; + } + } return server_xtn->orgquery (httpd, server, req, xpath, code, result); @@ -589,7 +608,9 @@ static struct { QSE_T("host['*'].location['/'].realm"), QSE_T("default.realm") }, { QSE_T("host['*'].location['/'].auth"), QSE_T("default.auth") }, { QSE_T("host['*'].location['/'].dir-css"), QSE_T("default.dir-css") }, - { QSE_T("host['*'].location['/'].error-css"), QSE_T("default.error-css") } + { QSE_T("host['*'].location['/'].error-css"), QSE_T("default.error-css") }, + { QSE_T("ssl-cert-file"), QSE_T("default.ssl-cert-file") }, + { QSE_T("ssl-key-file"), QSE_T("default.ssl-key-file") } }; static int load_server_config ( @@ -882,6 +903,7 @@ static qse_httpd_server_t* attach_server (qse_httpd_t* httpd, int num, qse_xli_l return QSE_NULL; } + qse_memset (&dope, 0, QSE_SIZEOF(dope)); if (qse_strtonwad (((qse_xli_str_t*)pair->val)->ptr, &dope.nwad) <= -1) { @@ -890,6 +912,10 @@ static qse_httpd_server_t* attach_server (qse_httpd_t* httpd, int num, qse_xli_l return QSE_NULL; } + pair = qse_xli_findpairbyname (httpd_xtn->xli, list, QSE_T("ssl")); + if (!pair) pair = qse_xli_findpairbyname (httpd_xtn->xli, QSE_NULL, QSE_T("default.ssl")); + if (pair && pair->val->type == QSE_XLI_STR) dope.flags |= QSE_HTTPD_SERVER_SECURE; + dope.detach = detach_server; xserver = qse_httpd_attachserverstd (httpd, &dope, QSE_SIZEOF(server_xtn_t)); if (xserver == QSE_NULL) @@ -914,6 +940,7 @@ static qse_httpd_server_t* attach_server (qse_httpd_t* httpd, int num, qse_xli_l /* remember the binding address used */ server_xtn->num = num; server_xtn->bind = dope.nwad; + server_xtn->secure = (dope.flags & QSE_HTTPD_SERVER_SECURE); return xserver; } @@ -1343,7 +1370,8 @@ int qse_main (int argc, qse_achar_t* argv[]) ret = qse_runmain (argc, argv, httpd_main); #if defined(HAVE_SSL) - /*ERR_remove_state ();*/ + /* ERR_remove_state() should be called for each thread if the application is thread */ + ERR_remove_state (0); ENGINE_cleanup (); ERR_free_strings (); EVP_cleanup (); diff --git a/qse/cmd/http/httpd.conf b/qse/cmd/http/httpd.conf index ec40e55e..65584ebe 100644 --- a/qse/cmd/http/httpd.conf +++ b/qse/cmd/http/httpd.conf @@ -3,6 +3,11 @@ # default { + # default ssl certificate file + #ssl-cert-file = "/etc/qse/cert.pem"; + # default ssl private key file + #ssl-key-file = "/etc/qse/key.pem"; + # the default name is used in http headers and in pages # generated by httpd. name = "QSEHTTPD v1"; @@ -55,14 +60,13 @@ default { server { bind = "0.0.0.0:1999"; + ssl = yes; - # ssl is not supported yet. - #ssl { - # certificate { - # private = "xxxx"; - # public = "xxxx"; - # } - #} + # openssl genrsa -out key.pem + # openssl req -new -key key.pem -out cert.csr + # openssl req -new -x509 -key key.pem -out cert.pem -days 1095 + ssl-cert-file = "/etc/qse/cert.pem"; + ssl-key-file = "/etc/qse/key.pem"; host "*" { location "/" { diff --git a/qse/configure b/qse/configure index e1ba7603..81400bd4 100755 --- a/qse/configure +++ b/qse/configure @@ -17442,7 +17442,7 @@ fi done -for ac_header in crt_externs.h prctl.h uci.h +for ac_header in crt_externs.h sys/prctl.h uci.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" diff --git a/qse/configure.ac b/qse/configure.ac index 6fa10daf..b6713ce0 100644 --- a/qse/configure.ac +++ b/qse/configure.ac @@ -121,7 +121,7 @@ AC_CHECK_HEADERS([net/if.h net/if_dl.h], [], [], [ #include #include ]) AC_CHECK_HEADERS([sys/stropts.h sys/macstat.h linux/ethtool.h linux/sockios.h]) -AC_CHECK_HEADERS([crt_externs.h prctl.h uci.h]) +AC_CHECK_HEADERS([crt_externs.h sys/prctl.h uci.h]) dnl check data types AC_CHECK_TYPE([wchar_t], diff --git a/qse/include/qse/config.h.in b/qse/include/qse/config.h.in index ba8e4cb4..11ea266d 100644 --- a/qse/include/qse/config.h.in +++ b/qse/include/qse/config.h.in @@ -302,9 +302,6 @@ /* Define to 1 if you have the `prctl' function. */ #undef HAVE_PRCTL -/* Define to 1 if you have the header file. */ -#undef HAVE_PRCTL_H - /* Define if libtool can extract symbol lists from object files. */ #undef HAVE_PRELOADED_SYMBOLS @@ -469,6 +466,9 @@ */ #undef HAVE_SYS_NDIR_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PRCTL_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_RESOURCE_H diff --git a/qse/include/qse/http/stdhttpd.h b/qse/include/qse/http/stdhttpd.h index 6b55d8d9..e89d1ca8 100644 --- a/qse/include/qse/http/stdhttpd.h +++ b/qse/include/qse/http/stdhttpd.h @@ -85,6 +85,13 @@ struct qse_httpd_serverstd_index_t const qse_mchar_t* files; /* "value1\0value2\0" */ }; +typedef struct qse_httpd_serverstd_ssl_t qse_httpd_serverstd_ssl_t; +struct qse_httpd_serverstd_ssl_t +{ + const qse_mchar_t* certfile; + const qse_mchar_t* keyfile; +}; + enum qse_httpd_serverstd_query_code_t { QSE_HTTPD_SERVERSTD_NAME, /* const qse_mchar_t* */ @@ -98,7 +105,9 @@ enum qse_httpd_serverstd_query_code_t QSE_HTTPD_SERVERSTD_CGI, /* qse_httpd_serverstd_cgi_t */ QSE_HTTPD_SERVERSTD_MIME, /* const qse_mchar_t* */ QSE_HTTPD_SERVERSTD_DIRACC, /* int (http error code) */ - QSE_HTTPD_SERVERSTD_FILEACC /* int (http error code) */ + QSE_HTTPD_SERVERSTD_FILEACC, /* int (http error code) */ + + QSE_HTTPD_SERVERSTD_SSL /* qse_httpd_serverstd_ssl_t */ }; typedef enum qse_httpd_serverstd_query_code_t qse_httpd_serverstd_query_code_t; diff --git a/qse/lib/http/httpd-std.c b/qse/lib/http/httpd-std.c index 737610c1..89b80b4d 100644 --- a/qse/lib/http/httpd-std.c +++ b/qse/lib/http/httpd-std.c @@ -530,32 +530,44 @@ struct httpd_xtn_t }; #if defined(HAVE_SSL) -static int init_xtn_ssl ( - qse_httpd_t* httpd, - const qse_mchar_t* pemfile, - const qse_mchar_t* keyfile/*, - const qse_mchar_t* chainfile*/) +static int init_xtn_ssl (qse_httpd_t* httpd, qse_httpd_server_t* server) { SSL_CTX* ctx; httpd_xtn_t* xtn; + server_xtn_t* server_xtn; + qse_httpd_serverstd_ssl_t ssl; xtn = (httpd_xtn_t*)qse_httpd_getxtn (httpd); + server_xtn = (server_xtn_t*)qse_httpd_getserverxtn (httpd, server); + + if (server_xtn->query (httpd, server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_SSL, &ssl) <= -1) + { + return -1; + } + + if (ssl.certfile == QSE_NULL || ssl.keyfile == QSE_NULL) + { + qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL); + return -1; + } ctx = SSL_CTX_new (SSLv23_server_method()); if (ctx == QSE_NULL) return -1; /*SSL_CTX_set_info_callback(ctx,ssl_info_callback);*/ - if (SSL_CTX_use_certificate_file (ctx, pemfile, SSL_FILETYPE_PEM) == 0 || - SSL_CTX_use_PrivateKey_file (ctx, keyfile, SSL_FILETYPE_PEM) == 0 || + if (SSL_CTX_use_certificate_file (ctx, ssl.certfile, SSL_FILETYPE_PEM) == 0 || + SSL_CTX_use_PrivateKey_file (ctx, ssl.keyfile, SSL_FILETYPE_PEM) == 0 || SSL_CTX_check_private_key (ctx) == 0 /*|| SSL_CTX_use_certificate_chain_file (ctx, chainfile) == 0*/) { if (httpd->opt.trait & QSE_HTTPD_LOGACT) { qse_httpd_act_t msg; + qse_size_t len; msg.code = QSE_HTTPD_CATCH_MERRMSG; - ERR_error_string_n (ERR_get_error(), msg.u.merrmsg, QSE_COUNTOF(msg.u.merrmsg)); + len = qse_mbscpy (msg.u.merrmsg, QSE_MT("cert/key file error - ")); + ERR_error_string_n (ERR_get_error(), &msg.u.merrmsg[len], QSE_COUNTOF(msg.u.merrmsg) - len); httpd->opt.rcb.logact (httpd, &msg); } @@ -606,10 +618,6 @@ qse_httpd_t* qse_httpd_openstdwithmmgr (qse_mmgr_t* mmgr, qse_size_t xtnsize) xtn = (httpd_xtn_t*)qse_httpd_getxtn (httpd); -#if defined(HAVE_SSL) - /*init_xtn_ssl (httpd, "http01.pem", "http01.key");*/ -#endif - set_httpd_callbacks (httpd); xtn->ecb.close = cleanup_standard_httpd; @@ -1725,8 +1733,7 @@ static int client_accepted (qse_httpd_t* httpd, qse_httpd_client_t* client) if (!xtn->ssl_ctx) { /* delayed initialization of ssl */ -/* TODO: certificate from options */ - if (init_xtn_ssl (httpd, "http01.pem", "http01.key") <= -1) + if (init_xtn_ssl (httpd, client->server) <= -1) { return -1; } @@ -2678,7 +2685,12 @@ static int query_server ( case QSE_HTTPD_SERVERSTD_FILEACC: *(int*)result = 200; return 0; - + + case QSE_HTTPD_SERVERSTD_SSL: + /* you must specify the certificate and the key file to be able + * to use SSL */ + qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOENT); + return -1; } qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL);