Fixed ssl client certs for evhtp.
* Added SSL cert info as options: CLICON_SSL_SERVER_CERT, CLICON_SSL_SERVER_KEY, CLICON_SSL_CA_CERT Added config.sh for testing for autotools
This commit is contained in:
parent
9c82e97072
commit
c049a397b0
22 changed files with 515 additions and 80 deletions
|
|
@ -35,9 +35,6 @@
|
|||
* libevhtp code
|
||||
*/
|
||||
|
||||
/* XXX temp constant should go away, */
|
||||
#undef _EVHTP_NYI
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clixon_config.h" /* generated by config & autoconf */
|
||||
#endif
|
||||
|
|
@ -82,7 +79,7 @@
|
|||
#include "restconf_root.h"
|
||||
|
||||
/* Command line options to be passed to getopt(3) */
|
||||
#define RESTCONF_OPTS "hD:f:l:p:d:y:a:u:o:P:s"
|
||||
#define RESTCONF_OPTS "hD:f:l:p:d:y:a:u:o:P:sc"
|
||||
|
||||
/* Need global variable to for signal handler XXX */
|
||||
static clicon_handle _CLICON_HANDLE = NULL;
|
||||
|
|
@ -100,9 +97,7 @@ restconf_sig_term(int arg)
|
|||
else
|
||||
exit(-1);
|
||||
if (_CLICON_HANDLE){
|
||||
#ifdef _EVHTP_NYI
|
||||
stream_child_freeall(_CLICON_HANDLE);
|
||||
#endif
|
||||
// stream_child_freeall(_CLICON_HANDLE);
|
||||
restconf_terminate(_CLICON_HANDLE);
|
||||
}
|
||||
clicon_exit_set(); /* checked in clixon_event_loop() */
|
||||
|
|
@ -116,9 +111,6 @@ restconf_sig_child(int arg)
|
|||
int pid;
|
||||
|
||||
if ((pid = waitpid(-1, &status, 0)) != -1 && WIFEXITED(status)){
|
||||
#ifdef _EVHTP_NYI
|
||||
;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -267,11 +259,16 @@ evhtp_params_set(clicon_handle h,
|
|||
evhtp_request_t *req,
|
||||
cvec *qvec)
|
||||
{
|
||||
int retval = -1;
|
||||
htp_method meth;
|
||||
evhtp_uri_t *uri;
|
||||
evhtp_path_t *path;
|
||||
int retval = -1;
|
||||
htp_method meth;
|
||||
evhtp_uri_t *uri;
|
||||
evhtp_path_t *path;
|
||||
evhtp_ssl_t *ssl = NULL;
|
||||
char *subject;
|
||||
cvec *cvv = NULL;
|
||||
char *cn;
|
||||
|
||||
|
||||
if ((uri = req->uri) == NULL){
|
||||
clicon_err(OE_DAEMON, EFAULT, "No uri");
|
||||
goto done;
|
||||
|
|
@ -303,9 +300,18 @@ evhtp_params_set(clicon_handle h,
|
|||
goto fail;
|
||||
}
|
||||
clicon_debug(1, "%s conn->ssl:%d", __FUNCTION__, req->conn->ssl?1:0);
|
||||
if (req->conn->ssl != NULL){
|
||||
if ((ssl = req->conn->ssl) != NULL){
|
||||
if (restconf_param_set(h, "HTTPS", "https") < 0) /* some string or NULL */
|
||||
goto done;
|
||||
/* SSL subject fields, eg CN (Common Name) , can add more here? */
|
||||
if ((subject = (char*)htp_sslutil_subject_tostr(req->conn->ssl)) != NULL){
|
||||
if (str2cvec(subject, '/', '=', &cvv) < 0)
|
||||
goto done;
|
||||
if ((cn = cvec_find_str(cvv, "CN")) != NULL){
|
||||
if (restconf_param_set(h, "SSL_CN", cn) < 0)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Translate all http headers by capitalizing, prepend w HTTP_ and - -> _
|
||||
|
|
@ -315,6 +321,8 @@ evhtp_params_set(clicon_handle h,
|
|||
goto done;
|
||||
retval = 1;
|
||||
done:
|
||||
if (cvv)
|
||||
cvec_free(cvv);
|
||||
return retval;
|
||||
fail:
|
||||
retval = 0;
|
||||
|
|
@ -423,6 +431,8 @@ cx_path_restconf(evhtp_request_t *req,
|
|||
/* input debug */
|
||||
if (clicon_debug_get())
|
||||
evhtp_headers_for_each(req->headers_in, print_header, h);
|
||||
|
||||
|
||||
/* get accepted connection */
|
||||
/* Query vector, ie the ?a=x&b=y stuff */
|
||||
if ((qvec = cvec_new(0)) ==NULL){
|
||||
|
|
@ -446,51 +456,93 @@ cx_path_restconf(evhtp_request_t *req,
|
|||
}
|
||||
|
||||
/*! Get Server cert info
|
||||
* @param[out] ssl_config
|
||||
* @param[in] h Clicon handle
|
||||
* @param[out] ssl_config evhtp ssl config struct
|
||||
*/
|
||||
static int
|
||||
get_servercerts(evhtp_ssl_cfg_t *ssl_config,
|
||||
const char *pki_dir,
|
||||
const char *ssl_server_cert)
|
||||
cx_get_certs(clicon_handle h,
|
||||
int ssl_verify_clients,
|
||||
evhtp_ssl_cfg_t *ssl_config)
|
||||
{
|
||||
int retval = -1;
|
||||
cbuf *cb = NULL;
|
||||
struct stat f_stat;
|
||||
char *filename;
|
||||
|
||||
if (ssl_config == NULL){
|
||||
clicon_err(OE_CFG, EINVAL, "ssl_config is NULL");
|
||||
clicon_err(OE_CFG, EINVAL, "Input parameter is NULL");
|
||||
goto done;
|
||||
}
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
if ((filename = clicon_option_str(h, "CLICON_SSL_SERVER_CERT")) == NULL){
|
||||
clicon_err(OE_CFG, EFAULT, "CLICON_SSL_SERVER_CERT option missing");
|
||||
goto done;
|
||||
}
|
||||
cprintf(cb, "%s/%s-crt.pem", pki_dir, ssl_server_cert);
|
||||
if ((ssl_config->pemfile = strdup(cbuf_get(cb))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "strdup");
|
||||
if ((ssl_config->pemfile = strdup(filename)) == NULL){
|
||||
clicon_err(OE_CFG, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
if (stat(ssl_config->pemfile, &f_stat) != 0) {
|
||||
clicon_err(OE_FATAL, errno, "Cannot load SSL cert '%s'", ssl_config->pemfile);
|
||||
goto done;
|
||||
}
|
||||
cbuf_reset(cb);
|
||||
cprintf(cb, "%s/%s-key.pem", pki_dir, ssl_server_cert);
|
||||
if ((ssl_config->privfile = strdup(cbuf_get(cb))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "strdup");
|
||||
if ((filename = clicon_option_str(h, "CLICON_SSL_SERVER_KEY")) == NULL){
|
||||
clicon_err(OE_CFG, EFAULT, "CLICON_SSL_SERVER_KEY option missing");
|
||||
goto done;
|
||||
}
|
||||
if ((ssl_config->privfile = strdup(filename)) == NULL){
|
||||
clicon_err(OE_CFG, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
if (stat(ssl_config->privfile, &f_stat) != 0) {
|
||||
clicon_err(OE_FATAL, errno, "Cannot load SSL key '%s'", ssl_config->privfile);
|
||||
goto done;
|
||||
}
|
||||
if (ssl_verify_clients){
|
||||
if ((filename = clicon_option_str(h, "CLICON_SSL_CA_CERT")) == NULL){
|
||||
clicon_err(OE_CFG, EFAULT, "CLICON_SSL_CA_CERT option missing");
|
||||
goto done;
|
||||
}
|
||||
if ((ssl_config->cafile = strdup(filename)) == NULL){
|
||||
clicon_err(OE_CFG, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
if (stat(ssl_config->cafile, &f_stat) != 0) {
|
||||
clicon_err(OE_FATAL, errno, "Cannot load SSL key '%s'", ssl_config->privfile);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int
|
||||
cx_verify_certs(int pre_verify,
|
||||
evhtp_x509_store_ctx_t *store)
|
||||
{
|
||||
#ifdef NOTYET
|
||||
char buf[256];
|
||||
X509 * err_cert;
|
||||
int err;
|
||||
int depth;
|
||||
SSL * ssl;
|
||||
evhtp_connection_t * connection;
|
||||
evhtp_ssl_cfg_t * ssl_cfg;
|
||||
|
||||
fprintf(stderr, "%s %d\n", __FUNCTION__, pre_verify);
|
||||
|
||||
err_cert = X509_STORE_CTX_get_current_cert(store);
|
||||
err = X509_STORE_CTX_get_error(store);
|
||||
depth = X509_STORE_CTX_get_error_depth(store);
|
||||
ssl = X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx());
|
||||
|
||||
X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
|
||||
|
||||
connection = SSL_get_app_data(ssl);
|
||||
ssl_cfg = connection->htp->ssl_cfg;
|
||||
#endif
|
||||
return pre_verify;
|
||||
}
|
||||
|
||||
/*! Usage help routine
|
||||
* @param[in] argv0 command line
|
||||
* @param[in] h Clicon handle
|
||||
|
|
@ -513,6 +565,7 @@ usage(clicon_handle h,
|
|||
"\t-u <path|addr>\t Internal socket domain path or IP addr (see -a)\n"
|
||||
"\t-o \"<option>=<value>\" Give configuration option overriding config file (see clixon-config.yang)\n"
|
||||
"\t-s\t SSL server, https\n"
|
||||
"\t-c\t SSL verify client certs\n"
|
||||
"\t-P <port>\t HTTP port (default 80, or 443 if -s is given)\n"
|
||||
,
|
||||
argv0,
|
||||
|
|
@ -521,6 +574,8 @@ usage(clicon_handle h,
|
|||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*! Main routine for libevhtp restconf
|
||||
*/
|
||||
int
|
||||
|
|
@ -541,15 +596,12 @@ main(int argc,
|
|||
size_t cligen_bufthreshold;
|
||||
uint16_t defaultport = 80;
|
||||
uint16_t port = 0;
|
||||
#ifdef _EVHTP_NYI
|
||||
char *stream_path;
|
||||
#endif
|
||||
evhtp_t *htp = NULL;
|
||||
struct event_base *evbase = NULL;
|
||||
evhtp_ssl_cfg_t *ssl_config = NULL;
|
||||
int dbg = 0;
|
||||
char *ssl_server = NULL; /* SSL server name, default "server", base for srv certs */
|
||||
char *pki_dir = CLIXON_PKI_DIR;
|
||||
int use_ssl = 0;
|
||||
int ssl_verify_clients = 0;
|
||||
|
||||
/* In the startup, logs to stderr & debug flag set later */
|
||||
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
||||
|
|
@ -607,9 +659,7 @@ main(int argc,
|
|||
/* Find and read configfile */
|
||||
if (clicon_options_main(h) < 0)
|
||||
goto done;
|
||||
#ifdef _EVHTP_NYI
|
||||
stream_path = clicon_option_str(h, "CLICON_STREAM_PATH");
|
||||
#endif
|
||||
// stream_path = clicon_option_str(h, "CLICON_STREAM_PATH");
|
||||
|
||||
/* Now rest of options, some overwrite option file */
|
||||
optind = 1;
|
||||
|
|
@ -651,9 +701,12 @@ main(int argc,
|
|||
break;
|
||||
}
|
||||
case 's': /* ssl: use https */
|
||||
ssl_server = CLIXON_SERVER_CERT;
|
||||
use_ssl = 1;
|
||||
defaultport = 443; /* unless explicit -P ? */
|
||||
break;
|
||||
case 'c': /* ssl: verify clients */
|
||||
ssl_verify_clients = 1;
|
||||
break;
|
||||
case 'P': /* http port */
|
||||
if (!strlen(optarg))
|
||||
usage(h, argv0);
|
||||
|
|
@ -669,7 +722,7 @@ main(int argc,
|
|||
if (port == 0)
|
||||
port = defaultport;
|
||||
/* Check server ssl certs */
|
||||
if (ssl_server){
|
||||
if (use_ssl){
|
||||
/* Init evhtp ssl config struct */
|
||||
if ((ssl_config = malloc(sizeof(evhtp_ssl_cfg_t))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "malloc");
|
||||
|
|
@ -678,8 +731,14 @@ main(int argc,
|
|||
memset(ssl_config, 0, sizeof(evhtp_ssl_cfg_t));
|
||||
ssl_config->ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
|
||||
|
||||
if (get_servercerts(ssl_config, pki_dir, ssl_server) < 0)
|
||||
if (cx_get_certs(h, ssl_verify_clients, ssl_config) < 0)
|
||||
goto done;
|
||||
ssl_config->x509_verify_cb = cx_verify_certs; /* Is extra verification necessary? */
|
||||
if (ssl_verify_clients){
|
||||
ssl_config->verify_peer = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
|
||||
ssl_config->x509_verify_cb = cx_verify_certs;
|
||||
ssl_config->verify_depth = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// ssl_verify_mode = htp_sslutil_verify2opts(optarg);
|
||||
|
|
@ -697,7 +756,7 @@ main(int argc,
|
|||
clicon_err(OE_UNIX, errno, "evhtp_new");
|
||||
goto done;
|
||||
}
|
||||
if (ssl_server){
|
||||
if (use_ssl){
|
||||
if (evhtp_ssl_init(htp, ssl_config) < 0){
|
||||
clicon_err(OE_UNIX, errno, "evhtp_new");
|
||||
goto done;
|
||||
|
|
@ -835,9 +894,7 @@ main(int argc,
|
|||
|
||||
retval = 0;
|
||||
done:
|
||||
#ifdef _EVHTP_NYI
|
||||
stream_child_freeall(h);
|
||||
#endif
|
||||
// stream_child_freeall(h);
|
||||
restconf_terminate(h);
|
||||
return retval;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue