diff --git a/CHANGELOG.md b/CHANGELOG.md index 1360ad07..701aac96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,7 @@ Users may have to change how they access the system ### Corrected Bugs +* Fixed: [yang regular char \w not include underline char](https://github.com/clicon/clixon/issues/357) * Fixed: [Clixon backend transactions for choice/case is not logical](https://github.com/clicon/clixon/issues/361) * Fixed: [Clixon backend transaction callback fails for empty types](https://github.com/clicon/clixon/issues/360) * Fixed: [with-defaults=trim does not work due to dodgy handling of state data marked as default](https://github.com/clicon/clixon/issues/348) diff --git a/apps/cli/cli_auto.c b/apps/cli/cli_auto.c index 41a00659..0e3d8b18 100644 --- a/apps/cli/cli_auto.c +++ b/apps/cli/cli_auto.c @@ -346,7 +346,7 @@ cli_auto_top(clicon_handle h, * "running"|"candidate"|"startup" * "text"|"xml"|"json"|"cli"|"netconf" (see format_enum) * true|false: pretty-print or not - * true|false: pretty-print or not + * true|false: include state in output * Retrieval default mode: report-all, trim, explicit, report-all-tagged, * report-all-tagged-default, report-all-tagged-strip * CLI prefix: to print before cli syntax output diff --git a/apps/restconf/restconf_main_native.c b/apps/restconf/restconf_main_native.c index be8e9264..ef7602f9 100644 --- a/apps/restconf/restconf_main_native.c +++ b/apps/restconf/restconf_main_native.c @@ -36,14 +36,22 @@ * Data structures: * 1 1 * +--------------------+ restconf_handle_get +--------------------+ - * | rh restconf_handle | <--------------------- | h clicon_handle | - * +--------------------+ +--------------------+ - * common SSL config \ ^ - * \ | n - * \ rh_sockets +--------------------+ - * +-----------> | rs restconf_socket | + * | rn restconf_native | <--------------------- | h clicon_handle | + * | _handle | +--------------------+ + * +--------------------+ ^ + * common SSL config \ | + * \ | n + * \ rn_sockets +--------------------+ + * +-----------> | rs restconf_socket | * +--------------------+ - * n per-socket SSL config + * per-server socket (per config) + * | ^ + * rs_conns v | n + * +--------------------+ + * | rc restconf_conn | + * +--------------------+ + * per-connection (transient) + * n * +--------------------+ * | rr restconf_request| per-packet * +--------------------+ @@ -449,38 +457,6 @@ restconf_ssl_context_configure(clixon_handle h, return retval; } -/*! Utility function to close restconf server ssl socket. - * There are many variants to closing, one could probably make this more generic - * and always use this function, but it is difficult. - */ -int -restconf_close_ssl_socket(restconf_conn *rc, - int shutdown) -{ - int retval = -1; - int ret; - - if (rc->rc_ssl != NULL){ - if (shutdown && (ret = SSL_shutdown(rc->rc_ssl)) < 0){ -#if 0 - case SSL_ERROR_ZERO_RETURN: /* 6 */ -Note that in this case SSL_ERROR_ZERO_RETURN does not necessarily indicate that the underlying transport has been closed. -#endif - int e = SSL_get_error(rc->rc_ssl, ret); - clicon_err(OE_SSL, 0, "SSL_shutdown, err:%d", e); - goto done; - } - SSL_free(rc->rc_ssl); - rc->rc_ssl = NULL; - } - if (restconf_connection_close(rc->rc_h, rc->rc_s, rc->rc_socket) < 0) - goto done; - retval = 0; - done: - clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); - return retval; -} - #if 0 /* debug */ /*! Debug print all loaded certs */ @@ -581,7 +557,7 @@ restconf_accept_client(int fd, goto done; } /* Accept SSL */ - if (restconf_ssl_accept_client(h, s, rsock) < 0) + if (restconf_ssl_accept_client(h, s, rsock, NULL) < 0) goto done; retval = 0; done: @@ -596,22 +572,29 @@ restconf_accept_client(int fd, static int restconf_native_terminate(clicon_handle h) { - restconf_native_handle *rh; + restconf_native_handle *rn; restconf_socket *rsock; + restconf_conn *rc; clicon_debug(1, "%s", __FUNCTION__); - if ((rh = restconf_native_handle_get(h)) != NULL){ - while ((rsock = rh->rh_sockets) != NULL){ + if ((rn = restconf_native_handle_get(h)) != NULL){ + while ((rsock = rn->rn_sockets) != NULL){ + while ((rc = rsock->rs_conns) != NULL){ + if (rc->rc_s != -1){ + clixon_event_unreg_fd(rc->rc_s, restconf_connection); + close(rc->rc_s); + } + DELQ(rc, rsock->rs_conns, restconf_conn *); + restconf_close_ssl_socket(rc, __FUNCTION__, 0); + } if (rsock->rs_callhome){ restconf_callhome_timer_unreg(rsock); - if (rsock->rs_periodic) - restconf_idle_timer_unreg(rsock); } else if (rsock->rs_ss != -1){ clixon_event_unreg_fd(rsock->rs_ss, restconf_accept_client); close(rsock->rs_ss); } - DELQ(rsock, rh->rh_sockets, restconf_socket *); + DELQ(rsock, rn->rn_sockets, restconf_socket *); if (rsock->rs_description) free(rsock->rs_description); if (rsock->rs_addrstr) @@ -620,9 +603,9 @@ restconf_native_terminate(clicon_handle h) free(rsock->rs_addrtype); free(rsock); } - if (rh->rh_ctx) - SSL_CTX_free(rh->rh_ctx); - free(rh); + if (rn->rn_ctx) + SSL_CTX_free(rn->rn_ctx); + free(rn); } EVP_cleanup(); return 0; @@ -716,7 +699,7 @@ openssl_init_socket(clicon_handle h, char *addrtype = NULL; uint16_t port = 0; int ss = -1; - restconf_native_handle *rh = NULL; + restconf_native_handle *rn = NULL; restconf_socket *rsock = NULL; /* openssl per socket struct */ struct timeval now; @@ -755,7 +738,7 @@ openssl_init_socket(clicon_handle h, ) < 0) goto done; } - if ((rh = restconf_native_handle_get(h)) == NULL){ + if ((rn = restconf_native_handle_get(h)) == NULL){ clicon_err(OE_XML, EFAULT, "No openssl handle"); goto done; } @@ -768,7 +751,7 @@ openssl_init_socket(clicon_handle h, goto done; } rsock->rs_port = port; - INSQ(rsock, rh->rh_sockets); + INSQ(rsock, rn->rn_sockets); if (rsock->rs_callhome){ rsock->rs_ss = -1; /* Not applicable from callhome */ @@ -809,7 +792,7 @@ restconf_openssl_init(clicon_handle h, char *server_cert_path = NULL; char *server_key_path = NULL; char *server_ca_cert_path = NULL; - restconf_native_handle *rh; + restconf_native_handle *rn; clixon_auth_type_t auth_type; int dbg; char *bstr; @@ -868,8 +851,8 @@ restconf_openssl_init(clicon_handle h, if (restconf_ssl_context_configure(h, ctx, server_cert_path, server_key_path, server_ca_cert_path) < 0) goto done; } - rh = restconf_native_handle_get(h); - rh->rh_ctx = ctx; + rn = restconf_native_handle_get(h); + rn->rn_ctx = ctx; /* get the list of socket config-data */ if (xpath_vec(xrestconf, nsc, "socket", &vec, &veclen) < 0) goto done; @@ -1123,7 +1106,7 @@ main(int argc, clicon_handle h; int dbg = 0; int logdst = CLICON_LOG_SYSLOG; - restconf_native_handle *rh = NULL; + restconf_native_handle *rn = NULL; int ret; cxobj *xrestconf = NULL; char *inline_config = NULL; @@ -1286,12 +1269,12 @@ main(int argc, goto done; } /* Create and stroe global openssl handle */ - if ((rh = malloc(sizeof *rh)) == NULL){ + if ((rn = malloc(sizeof *rn)) == NULL){ clicon_err(OE_UNIX, errno, "malloc"); goto done; } - memset(rh, 0, sizeof *rh); - if (restconf_native_handle_set(h, rh) < 0) + memset(rn, 0, sizeof *rn); + if (restconf_native_handle_set(h, rn) < 0) goto done; /* Openssl inits */ if (restconf_openssl_init(h, dbg, xrestconf) < 0) @@ -1305,7 +1288,6 @@ main(int argc, /* Main event loop */ if (clixon_event_loop(h) < 0) goto done; - clicon_debug(1, "%s after", __FUNCTION__); retval = 0; done: clicon_debug(1, "restconf_main_openssl done"); diff --git a/apps/restconf/restconf_methods_get.c b/apps/restconf/restconf_methods_get.c index de28c60e..e24aaff4 100644 --- a/apps/restconf/restconf_methods_get.c +++ b/apps/restconf/restconf_methods_get.c @@ -271,6 +271,10 @@ api_data_get2(clicon_handle h, goto done; if (xmlns_set_all(x, nscd) < 0) goto done; + if (nscd){ + cvec_free(nscd); + nscd = NULL; + } if (clixon_xml2cbuf(cbx, x, 0, pretty, -1, 0) < 0) /* Dont print top object? */ goto done; } @@ -301,7 +305,7 @@ api_data_get2(clicon_handle h, if (xpath) free(xpath); if (nscd) - xml_nsctx_free(nscd); + cvec_free(nscd); if (nsc) xml_nsctx_free(nsc); if (xtop) diff --git a/apps/restconf/restconf_native.c b/apps/restconf/restconf_native.c index 4563f9a9..340b285b 100644 --- a/apps/restconf/restconf_native.c +++ b/apps/restconf/restconf_native.c @@ -164,7 +164,12 @@ restconf_stream_free(restconf_stream_data *sd) return 0; } -/*! Create restconf connection struct +/*! Create restconf connection struct, per connect, ie transient + * + * @param[in] h Clixon handle + * @param[in] s Connected socket + * @param[in] rsock Backpointer to server struct + * @see restconf_conn_free */ restconf_conn * restconf_conn_new(clicon_handle h, @@ -180,22 +185,30 @@ restconf_conn_new(clicon_handle h, memset(rc, 0, sizeof(restconf_conn)); rc->rc_h = h; rc->rc_s = s; + rc->rc_callhome = rsock->rs_callhome; rc->rc_socket = rsock; + INSQ(rc, rsock->rs_conns); + clicon_debug(1, "%s %p", __FUNCTION__, rc); return rc; } /*! Free clixon/cbuf resources related to a connection * @param[in] rc restconf connection */ -int +static int restconf_conn_free(restconf_conn *rc) { + int retval = -1; restconf_stream_data *sd; - + restconf_socket *rsock; + restconf_conn *rc1; + + clicon_debug(1, "%s", __FUNCTION__); if (rc == NULL){ clicon_err(OE_RESTCONF, EINVAL, "rc is NULL"); - return -1; + goto done; } + clicon_debug(1, "%s %p", __FUNCTION__, rc); #ifdef HAVE_LIBNGHTTP2 if (rc->rc_ngsession) nghttp2_session_del(rc->rc_ngsession); @@ -206,8 +219,21 @@ restconf_conn_free(restconf_conn *rc) if (sd) restconf_stream_free(sd); } + /* Free connect from server sock */ + if ((rsock = rc->rc_socket) != NULL && + (rc1 = rsock->rs_conns) != NULL){ + do { + if (rc == rc1){ + DELQ(rc, rsock->rs_conns, restconf_conn *); + break; + } + rc1 = NEXTQ(restconf_conn *, rc1); + } while (rc1 && rc1 != rsock->rs_conns); + } free(rc); - return 0; + retval = 0; + done: + return retval; } /*! Given SSL connection, get peer certificate one-line name @@ -337,20 +363,27 @@ restconf_connection_sanity(clicon_handle h, /* Write buf to socket * see also this function in restcont_api_openssl.c + * @retval 1 OK + * @retval 0 OK, but socket write returned error, caller should close rc + * @retval -1 Error */ static int native_buf_write(clicon_handle h, char *buf, size_t buflen, - int s, - SSL *ssl, - restconf_socket *rsock) + restconf_conn *rc) { int retval = -1; ssize_t len; ssize_t totlen = 0; int er; + SSL *ssl; + if (rc == NULL){ + clicon_err(OE_RESTCONF, EINVAL, "rc is NULL"); + goto done; + } + ssl = rc->rc_ssl; /* Two problems with debugging buffers that this fixes: * 1. they are not "strings" in the sense they are not NULL-terminated * 2. they are often very long @@ -376,12 +409,9 @@ native_buf_write(clicon_handle h, case SSL_ERROR_SYSCALL: /* 5 */ if (er == ECONNRESET || /* Connection reset by peer */ er == EPIPE) { /* Reading end of socket is closed */ - if (ssl){ - SSL_free(ssl); - } - if (restconf_connection_close(h, s, rsock) < 0) + if (0 && restconf_close_ssl_socket(rc, __FUNCTION__, 0) < 0) goto done; - goto ok; /* Close socket and ssl */ + goto closed; /* Close socket and ssl */ } else if (er == EAGAIN){ clicon_debug(1, "%s write EAGAIN", __FUNCTION__); @@ -402,7 +432,7 @@ native_buf_write(clicon_handle h, } } else{ - if ((len = write(s, buf+totlen, buflen-totlen)) < 0){ + if ((len = write(rc->rc_s, buf+totlen, buflen-totlen)) < 0){ switch (errno){ case EAGAIN: /* Operation would block */ clicon_debug(1, "%s write EAGAIN", __FUNCTION__); @@ -412,9 +442,9 @@ native_buf_write(clicon_handle h, // case EBADF: // XXX if this happens there is some larger error case ECONNRESET: /* Connection reset by peer */ case EPIPE: /* Broken pipe */ - if (restconf_connection_close(h, s, rsock) < 0) + if (0 && restconf_close_ssl_socket(rc, __FUNCTION__, 0) < 0) goto done; - goto ok; /* Close socket and ssl */ + goto closed; /* Close socket and ssl */ break; default: clicon_err(OE_UNIX, errno, "write %d", errno); @@ -426,27 +456,30 @@ native_buf_write(clicon_handle h, } totlen += len; } /* while */ - ok: - retval = 0; + retval = 1; done: clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); return retval; + closed: + retval = 0; + goto done; } /*! Send early handcoded bad request reply before actual packet received, just after accept * @param[in] h Clixon handle - * @param[in] s Socket - * @param[in] ssl If set, it will be freed + * @param[in] media * @param[in] body If given add message body using media + * @param[in] rc Restconf connection, note may be closed in this + * @retval 1 OK + * @retval 0 OK, but socket write returned error, caller should close rc + * @retval -1 Error * @see restconf_badrequest which can only be called in a request context */ static int -native_send_badrequest(clicon_handle h, - int s, - SSL *ssl, - char *media, - char *body, - restconf_socket *rsock) +native_send_badrequest(clicon_handle h, + char *media, + char *body, + restconf_conn *rc) { int retval = -1; cbuf *cb = NULL; @@ -466,9 +499,7 @@ native_send_badrequest(clicon_handle h, cprintf(cb, "\r\n"); if (body) cprintf(cb, "%s\r\n", body); - if (native_buf_write(h, cbuf_get(cb), cbuf_len(cb), s, ssl, rsock) < 0) // XXX rsock - goto done; - retval = 0; + retval = native_buf_write(h, cbuf_get(cb), cbuf_len(cb), rc); done: if (cb) cbuf_free(cb); @@ -579,9 +610,8 @@ read_regular(restconf_conn *rc, switch(errno){ case ECONNRESET:/* Connection reset by peer */ clicon_debug(1, "%s %d Connection reset by peer", __FUNCTION__, rc->rc_s); - if (restconf_connection_close(rc->rc_h, rc->rc_s, rc->rc_socket) < 0) + if (restconf_close_ssl_socket(rc, __FUNCTION__, 0) < 0) goto done; - restconf_conn_free(rc); retval = 0; /* Close socket and ssl */ goto done; break; @@ -614,10 +644,10 @@ read_regular(restconf_conn *rc, * @retval 1 OK */ static int -restconf_http1_process(restconf_conn *rc, - char *buf, - size_t n, - int *readmore) +restconf_http1_process(restconf_conn *rc, + char *buf, + size_t n, + int *readmore) { int retval = -1; restconf_stream_data *sd; @@ -680,7 +710,7 @@ restconf_http1_process(restconf_conn *rc, goto done; } cprintf(cberr, "protocolmalformed-message%s", clicon_err_reason); - if (native_send_badrequest(h, rc->rc_s, rc->rc_ssl, "application/yang-data+xml", cbuf_get(cberr), rc->rc_socket) < 0) + if ((ret = native_send_badrequest(h, "application/yang-data+xml", cbuf_get(cberr), rc)) < 0) goto done; goto ok; } @@ -690,11 +720,17 @@ restconf_http1_process(restconf_conn *rc, if ((ret = http1_check_expect(h, rc, sd)) < 0) goto done; if (ret == 1){ - if (native_buf_write(h, cbuf_get(sd->sd_outp_buf), cbuf_len(sd->sd_outp_buf), - rc->rc_s, rc->rc_ssl, rc->rc_socket) < 0) + if ((ret = native_buf_write(h, cbuf_get(sd->sd_outp_buf), cbuf_len(sd->sd_outp_buf), rc)) < 0) goto done; cvec_reset(sd->sd_outp_hdrs); cbuf_reset(sd->sd_outp_buf); + if (ret == 0){ + if (restconf_close_ssl_socket(rc, __FUNCTION__, 0) < 0) + goto done; + rc = NULL; + retval = 0; + goto done; + } } } /* Check whole message is read. @@ -718,19 +754,15 @@ restconf_http1_process(restconf_conn *rc, /* main restconf processing */ if (restconf_http1_path_root(h, rc) < 0) goto done; - if (native_buf_write(h, cbuf_get(sd->sd_outp_buf), cbuf_len(sd->sd_outp_buf), - rc->rc_s, rc->rc_ssl, rc->rc_socket) < 0) + if ((ret = native_buf_write(h, cbuf_get(sd->sd_outp_buf), cbuf_len(sd->sd_outp_buf), rc)) < 0) goto done; cvec_reset(sd->sd_outp_hdrs); /* Can be done in native_send_reply */ cbuf_reset(sd->sd_outp_buf); cbuf_reset(sd->sd_inbuf); cbuf_reset(sd->sd_indata); - if (rc->rc_exit){ /* Server-initiated exit */ - SSL_free(rc->rc_ssl); - rc->rc_ssl = NULL; - if (restconf_connection_close(h, rc->rc_s, rc->rc_socket) < 0) + if (ret == 0 || rc->rc_exit){ /* Server-initiated exit */ + if (restconf_close_ssl_socket(rc, __FUNCTION__, 0) < 0) goto done; - restconf_conn_free(rc); retval = 0; goto done; } @@ -761,7 +793,7 @@ restconf_http2_upgrade(restconf_conn *rc) /* Switch to http/2 according to RFC 7540 Sec 3.2 and RFC 7230 Sec 6.7 */ rc->rc_proto = HTTP_2; if (http2_session_init(rc) < 0){ - restconf_close_ssl_socket(rc, 1); + restconf_close_ssl_socket(rc, __FUNCTION__, 0); goto done; } /* The HTTP/1.1 request that is sent prior to upgrade is assigned a @@ -780,7 +812,7 @@ restconf_http2_upgrade(restconf_conn *rc) goto done; } if (http2_send_server_connection(rc) < 0){ - restconf_close_ssl_socket(rc, 1); + restconf_close_ssl_socket(rc, __FUNCTION__, 0); goto done; } /* Use params from original http/1 session to http/2 stream */ @@ -836,8 +868,7 @@ restconf_http2_process(restconf_conn *rc, if ((ret = http2_recv(rc, (unsigned char *)buf, n)) < 0) goto done; if (ret == 0){ - restconf_close_ssl_socket(rc, 0); - if (restconf_conn_free(rc) < 0) + if (restconf_close_ssl_socket(rc, __FUNCTION__, 0) < 0) goto done; retval = 0; goto done; @@ -860,7 +891,7 @@ restconf_http2_process(restconf_conn *rc, /*! Get restconf native handle * @param[in] h Clicon handle - * @retval rh Restconf native handle + * @retval rn Restconf native handle */ restconf_native_handle * restconf_native_handle_get(clicon_handle h) @@ -925,9 +956,8 @@ restconf_connection(int s, continue; if (n == 0){ clicon_debug(1, "%s n=0 closing socket", __FUNCTION__); - if (restconf_close_ssl_socket(rc, 0) < 0) + if (restconf_close_ssl_socket(rc, __FUNCTION__, 0) < 0) goto done; - restconf_conn_free(rc); rc = NULL; goto ok; } @@ -966,27 +996,33 @@ restconf_connection(int s, return retval; } /* restconf_connection */ +/*----------------------------- Close socket ------------------------------*/ + /*! Close Restconf native connection socket and unregister callback * For callhome also start reconnect timer + * @param[in] rc rstconf connection */ -int -restconf_connection_close(clicon_handle h, - int s, - restconf_socket *rsock) +static int +restconf_connection_close1(restconf_conn *rc) { - int retval = -1; + int retval = -1; + restconf_socket *rsock; - clicon_debug(1, "%s %s", __FUNCTION__, rsock->rs_description); - if (close(s) < 0){ + if (rc == NULL){ + clicon_err(OE_RESTCONF, EINVAL, "rc is NULL"); + goto done; + } + rsock = rc->rc_socket; + clicon_debug(1, "%s \"%s\"", __FUNCTION__, rsock->rs_description); + if (close(rc->rc_s) < 0){ clicon_err(OE_UNIX, errno, "close"); goto done; } - clixon_event_unreg_fd(s, restconf_connection); + clixon_event_unreg_fd(rc->rc_s, restconf_connection); /* re-set timer */ - if (rsock->rs_callhome){ - if (rsock->rs_periodic && - restconf_idle_timer_unreg(rsock) < 0) - goto done; + if (rc->rc_callhome){ + if (rsock->rs_periodic) + restconf_idle_timer_unreg(rc); if (restconf_callhome_timer(rsock, 1) < 0) goto done; } @@ -995,7 +1031,62 @@ restconf_connection_close(clicon_handle h, clicon_debug(1, "%s %d", __FUNCTION__, retval); return retval; } - + +/*! Utility function to close restconf server ssl socket. + * There are many variants to closing, one could probably make this more generic + * and always use this function, but it is difficult. + * @param[in] rc restconf connection + * @param[in] callfn For debug + * @param[in] dontshutdown If != 0, do not shutdown + */ +int +restconf_close_ssl_socket(restconf_conn *rc, + const char *callfn, + int dontshutdown) +{ + int retval = -1; + int ret; + int sslerr; + int er; + + clicon_debug(1, "%s", __FUNCTION__); + if (rc->rc_ssl != NULL){ + if (!dontshutdown && + (ret = SSL_shutdown(rc->rc_ssl)) < 0){ + er = errno; + sslerr = SSL_get_error(rc->rc_ssl, ret); + clicon_debug(1, "%s errno:%d sslerr:%d", __FUNCTION__, er, sslerr); + // case SSL_ERROR_ZERO_RETURN: /* 6 */ + // Note that in this case SSL_ERROR_ZERO_RETURN does not necessarily indicate that the underlying transport has been closed. + if (sslerr == SSL_ERROR_SSL){ /* 1 */ + + } + else if (sslerr == SSL_ERROR_SYSCALL){ /* 5 */ + /* Some non-recoverable, fatal I/O error occurred. The OpenSSL error queue + may contain more information on the error. For socket I/O on Unix systems, + consult errno for details. If this error occurs then no further I/O + operations should be performed on the connection and SSL_shutdown() must + not be called.*/ + /* Ignore eg EBADF/ECONNRESET/EPIPE */ + } + else{ + clicon_err(OE_SSL, sslerr, "SSL_shutdown, %s err:%d %d", callfn, sslerr, er); + goto done; + } + } + SSL_free(rc->rc_ssl); + rc->rc_ssl = NULL; + } + if (restconf_connection_close1(rc) < 0) + goto done; + if (restconf_conn_free(rc) < 0) + goto done; + retval = 0; + done: + clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); + return retval; +} + /*------------------------------ Accept--------------------------------*/ /*! Check ALPN result @@ -1012,7 +1103,6 @@ ssl_alpn_check(clicon_handle h, restconf_http_proto *proto) { int retval = -1; - int ret; cbuf *cberr = NULL; clicon_debug(1, "%s", __FUNCTION__); @@ -1037,34 +1127,17 @@ ssl_alpn_check(clicon_handle h, if (alpn != NULL){ cprintf(cberr, "protocolmalformed-messageALPN: protocol not recognized: %s", alpn); clicon_log(LOG_INFO, "%s Warning: %s", __FUNCTION__, cbuf_get(cberr)); - if (native_send_badrequest(h, rc->rc_s, rc->rc_ssl, - "application/yang-data+xml", - cbuf_get(cberr), rc->rc_socket) < 0) + if (native_send_badrequest(h, + "application/yang-data+xml", + cbuf_get(cberr), rc) < 0) goto done; } else{ /* XXX Sending badrequest here gives a segv in SSL_shutdown() later or a SIGPIPE here */ clicon_log(LOG_INFO, "%s Warning: ALPN: No protocol selected, or no ALPN?", __FUNCTION__); } - - if (rc->rc_ssl){ - /* nmap ssl-known-key SEGV at s->method->ssl_shutdown(s); - * OR OpenSSL error: : SSL_shutdown, err: SSL_ERROR_SYSCALL(5) - */ - if ((ret = SSL_shutdown(rc->rc_ssl)) < 0){ - int e = SSL_get_error(rc->rc_ssl, ret); - if (e == SSL_ERROR_SYSCALL){ - clicon_log(LOG_INFO, "%s Warning: SSL_shutdown SSL_ERROR_SYSCALL", __FUNCTION__); - /* Continue */ - } - else { - clicon_err(OE_SSL, 0, "SSL_shutdown, err:%d", e); - goto done; - } - } - SSL_free(rc->rc_ssl); - } - restconf_conn_free(rc); + if (restconf_close_ssl_socket(rc, __FUNCTION__, 0) < 0) + goto done; } retval = 0; /* ALPN not OK */ done: @@ -1078,15 +1151,18 @@ ssl_alpn_check(clicon_handle h, * @param[in] h Clixon handle * @param[in] s Socket (unix or ip) * @param[in] rsock Socket struct + * @param[out] rcp Restconf connection * @see openssl_init_socket where this callback is registered */ int restconf_ssl_accept_client(clicon_handle h, int s, - restconf_socket *rsock) + restconf_socket *rsock, + restconf_conn **rcp + ) { int retval = -1; - restconf_native_handle *rh = NULL; + restconf_native_handle *rn = NULL; restconf_conn *rc = NULL; char *name = NULL; int ret; @@ -1103,7 +1179,7 @@ restconf_ssl_accept_client(clicon_handle h, proto = HTTP_2; /* If nghttp2 only let default be 2.0 */ #endif #endif - if ((rh = restconf_native_handle_get(h)) == NULL){ + if ((rn = restconf_native_handle_get(h)) == NULL){ clicon_err(OE_XML, EFAULT, "No openssl handle"); goto done; } @@ -1114,7 +1190,7 @@ restconf_ssl_accept_client(clicon_handle h, goto done; clicon_debug(1, "%s s:%d", __FUNCTION__, rc->rc_s); if (rsock->rs_ssl){ - if ((rc->rc_ssl = SSL_new(rh->rh_ctx)) == NULL){ + if ((rc->rc_ssl = SSL_new(rn->rn_ctx)) == NULL){ clicon_err(OE_SSL, 0, "SSL_new"); goto done; } @@ -1160,11 +1236,15 @@ restconf_ssl_accept_client(clicon_handle h, switch (e){ case SSL_ERROR_SSL: /* 1 */ clicon_debug(1, "%s SSL_ERROR_SSL (non-ssl message on ssl socket)", __FUNCTION__); +#ifdef HTTP_ON_HTTPS_REPLY SSL_free(rc->rc_ssl); rc->rc_ssl = NULL; - if (restconf_connection_close(h, rc->rc_s, rc->rc_socket) < 0) + if (native_send_badrequest(h, "application/yang-data+xml", + "protocolmalformed-messageThe plain HTTP request was sent to HTTPS port", rc) < 0) + goto done; +#endif + if (restconf_close_ssl_socket(rc, __FUNCTION__, 1) < 0) goto done; - restconf_conn_free(rc); goto ok; break; case SSL_ERROR_SYSCALL: /* 5 */ @@ -1174,9 +1254,8 @@ restconf_ssl_accept_client(clicon_handle h, operations should be performed on the connection and SSL_shutdown() must not be called.*/ clicon_debug(1, "%s SSL_accept() SSL_ERROR_SYSCALL %d", __FUNCTION__, er); - if (restconf_close_ssl_socket(rc, 0) < 0) + if (restconf_close_ssl_socket(rc, __FUNCTION__, 1) < 0) goto done; - restconf_conn_free(rc); rc = NULL; goto ok; break; @@ -1237,18 +1316,10 @@ restconf_ssl_accept_client(clicon_handle h, else { /* Get certificates (if available) */ if (proto != HTTP_2 && native_send_badrequest(h, rc->rc_s, rc->rc_ssl, "application/yang-data+xml", - "protocolmalformed-messagePeer certificate required", rc->rc_socket) < 0) + "protocolmalformed-messagePeer certificate required", rc->rc_socket, rc) < 0) + goto done; + if (restconf_close_ssl_socket(rc, __FUNCTION__, 0) < 0) goto done; - restconf_conn_free(rc); - if (rc->rc_ssl){ - if ((ret = SSL_shutdown(rc->rc_ssl)) < 0){ - int e = SSL_get_error(rc->rc_ssl, ret); - clicon_err(OE_SSL, 0, "SSL_shutdown, err:%d", e); - goto done; - } - SSL_free(rc->rc_ssl); - rc->rc_ssl = NULL; - } goto ok; } } @@ -1291,25 +1362,11 @@ restconf_ssl_accept_client(clicon_handle h, #ifdef HAVE_LIBNGHTTP2 case HTTP_2:{ if (http2_session_init(rc) < 0){ - restconf_close_ssl_socket(rc, 1); + restconf_close_ssl_socket(rc, __FUNCTION__, 0); goto done; } if (http2_send_server_connection(rc) < 0){ - restconf_close_ssl_socket(rc, 1); -#ifdef NYI - if (ssl) { - SSL_shutdown(ssl); - } - bufferevent_free(session_data->bev); - nghttp2_session_del(session_data->session); - for (stream_data = session_data->root.next; stream_data;) { - http2_stream_data *next = stream_data->next; - delete_http2_stream_data(stream_data); - stream_data = next; - } - free(session_data->client_addr); - free(session_data); -#endif + restconf_close_ssl_socket(rc, __FUNCTION__, 0); goto done; } break; @@ -1320,6 +1377,8 @@ restconf_ssl_accept_client(clicon_handle h, } /* switch proto */ if (clixon_event_reg_fd(rc->rc_s, restconf_connection, (void*)rc, "restconf client socket") < 0) goto done; + if (rcp) + *rcp = rc; ok: retval = 0; done: @@ -1330,6 +1389,7 @@ restconf_ssl_accept_client(clicon_handle h, } /* restconf_ssl_accept_client */ /*! idle timeout timer callback + * @param[in] rc restconf connection, more specifically: callhome connection */ static int restconf_idle_cb(int fd, @@ -1337,15 +1397,20 @@ restconf_idle_cb(int fd, { int retval = -1; restconf_socket *rsock; + restconf_conn *rc; - if ((rsock = (restconf_socket *)arg) == NULL){ + if ((rc = (restconf_conn *)arg) == NULL){ + clicon_err(OE_YANG, EINVAL, "rc is NULL"); + goto done; + } + if ((rsock = rc->rc_socket) == NULL){ clicon_err(OE_YANG, EINVAL, "rsock is NULL"); goto done; } - clicon_debug(1, "%s %s", __FUNCTION__, rsock->rs_description); + clicon_debug(1, "%s \"%s\"", __FUNCTION__, rsock->rs_description); /* sanity */ - if (rsock->rs_callhome && rsock->rs_periodic && rsock->rs_idle_timeout && rsock->rs_ss > 0){ - if (restconf_connection_close(rsock->rs_h, rsock->rs_ss, rsock) < 0) + if (rc->rc_callhome && rsock->rs_periodic && rsock->rs_idle_timeout && rc->rc_s > 0){ + if (restconf_close_ssl_socket(rc, __FUNCTION__, 0) < 0) goto done; } retval = 0; @@ -1354,9 +1419,9 @@ restconf_idle_cb(int fd, } int -restconf_idle_timer_unreg(restconf_socket *rsock) +restconf_idle_timer_unreg(restconf_conn *rc) { - return clixon_event_unreg_timeout(restconf_idle_cb, rsock); + return clixon_event_unreg_timeout(restconf_idle_cb, rc); } /*! Set callhome periodic idle-timeout @@ -1370,19 +1435,25 @@ restconf_idle_timer_unreg(restconf_socket *rsock) * @see restconf_idle_timer_unreg */ int -restconf_idle_timer(restconf_socket *rsock) +restconf_idle_timer(restconf_conn *rc) { int retval = -1; struct timeval now; struct timeval t; struct timeval t1 = {0, 0}; cbuf *cb = NULL; + restconf_socket *rsock; - if (rsock == NULL || !rsock->rs_callhome || !rsock->rs_periodic || rsock->rs_idle_timeout==0){ - clicon_err(OE_YANG, EINVAL, "rsock is NULL or not periodic callhome"); + if (rc == NULL || !rc->rc_callhome){ + clicon_err(OE_YANG, EINVAL, "rc is NULL or not callhome"); goto done; } - clicon_debug(1, "%s %s register", __FUNCTION__, rsock->rs_description); + rsock = rc->rc_socket; + if (rsock == NULL || !rsock->rs_periodic || rsock->rs_idle_timeout==0){ + clicon_err(OE_YANG, EINVAL, "rsock is NULL or not periodic"); + goto done; + } + clicon_debug(1, "%s \"%s\" register", __FUNCTION__, rsock->rs_description); if ((cb = cbuf_new()) == NULL){ clicon_err(OE_UNIX, errno, "cbuf_new"); goto done; @@ -1394,7 +1465,7 @@ restconf_idle_timer(restconf_socket *rsock) clicon_debug(1, "%s now:%lu timeout:%lu.%lu", __FUNCTION__, now.tv_sec, t.tv_sec, t.tv_usec); if (clixon_event_reg_timeout(t, restconf_idle_cb, - rsock, + rc, cbuf_get(cb)) < 0) goto done; retval = 0; @@ -1423,13 +1494,14 @@ restconf_callhome_cb(int fd, struct sockaddr *sa = (struct sockaddr *)&sin6; size_t sa_len; int s; + restconf_conn *rc = NULL; rsock = (restconf_socket *)arg; if (rsock == NULL || !rsock->rs_callhome){ clicon_err(OE_YANG, EINVAL, "rsock is NULL"); goto done; } - clicon_debug(1, "%s %s", __FUNCTION__, rsock->rs_description); + clicon_debug(1, "%s \"%s\"", __FUNCTION__, rsock->rs_description); h = rsock->rs_h; /* Already computed in restconf_socket_init, could be saved in rsock? */ if (clixon_inet2sin(rsock->rs_addrtype, rsock->rs_addrstr, rsock->rs_port, sa, &sa_len) < 0) @@ -1438,26 +1510,23 @@ restconf_callhome_cb(int fd, clicon_err(OE_UNIX, errno, "socket"); goto done; } - clicon_debug(1, "%s connect %hu", __FUNCTION__, rsock->rs_port); if (connect(s, sa, sa_len) < 0){ - clicon_debug(1, "%s connect:%d %s", __FUNCTION__, errno, strerror(errno)); + clicon_debug(1, "%s connect %hu fail:%d %s", __FUNCTION__, rsock->rs_port, errno, strerror(errno)); close(s); rsock->rs_attempts++; - rsock->rs_ss = -1; /* Fail: Initiate new timer */ if (restconf_callhome_timer(rsock, 0) < 0) goto done; } else { - rsock->rs_ss = s; + clicon_debug(1, "%s connect %hu OK", __FUNCTION__, rsock->rs_port); rsock->rs_attempts = 0; - if (restconf_ssl_accept_client(h, s, rsock) < 0) + if (restconf_ssl_accept_client(h, s, rsock, &rc) < 0) goto done; if (rsock->rs_periodic && rsock->rs_idle_timeout && - restconf_idle_timer(rsock) < 0) + restconf_idle_timer(rc) < 0) goto done; } - clicon_debug(1, "%s connect done", __FUNCTION__); retval = 0; done: return retval; @@ -1491,7 +1560,7 @@ restconf_callhome_timer(restconf_socket *rsock, clicon_err(OE_YANG, EINVAL, "rsock is NULL or not callhome"); goto done; } - clicon_debug(1, "%s %s", __FUNCTION__, rsock->rs_description); + clicon_debug(1, "%s \"%s\"", __FUNCTION__, rsock->rs_description); if (!rsock->rs_callhome) goto ok; /* shouldnt happen */ gettimeofday(&now, NULL); @@ -1519,7 +1588,7 @@ restconf_callhome_timer(restconf_socket *rsock, } cprintf(cb, "restconf callhome timer %s", rsock->rs_description); if (rsock->rs_description) - clicon_debug(1, "%s registering %s: %lu", __FUNCTION__, rsock->rs_description, t.tv_sec); + clicon_debug(1, "%s registering \"%s\": %lu", __FUNCTION__, rsock->rs_description, t.tv_sec); else clicon_debug(1, "%s: %lu", __FUNCTION__, t.tv_sec); /* Should be only place restconf_callhome_cb is registered */ diff --git a/apps/restconf/restconf_native.h b/apps/restconf/restconf_native.h index 3f7bcde5..23477527 100644 --- a/apps/restconf/restconf_native.h +++ b/apps/restconf/restconf_native.h @@ -32,16 +32,25 @@ ***** END LICENSE BLOCK ***** * + * Data structures: * 1 1 * +--------------------+ restconf_handle_get +--------------------+ - * | rh restconf_handle | <--------------------- | h clicon_handle | - * +--------------------+ +--------------------+ - * common SSL config \ ^ - * \ | n - * \ rh_sockets +--------------------+ - * +-----------> | rs restconf_socket | + * | rn restconf_native | <--------------------- | h clicon_handle | + * | _handle | +--------------------+ + * +--------------------+ ^ + * common SSL config \ | + * \ | n + * \ rn_sockets +--------------------+ + * +-----------> | rs restconf_socket | * +--------------------+ - * n per-socket SSL config + * per-server socket (per config) + * | ^ + * rs_conns v | n + * +--------------------+ + * | rc restconf_conn | + * +--------------------+ + * per-connection (transient) + * n * +--------------------+ * | rr restconf_request| per-packet * +--------------------+ @@ -85,44 +94,17 @@ typedef struct { uint8_t *sd_settings2; /* Settings for upgrade to http/2 request */ } restconf_stream_data; -/* Restconf per socket handle - * Two types: listen and callhome. - * Listen: Uses socket rs_ss to listen for connections and accepts them, creates one - * restconf_conn for each new accept. - * Callhome: Calls connect according to timer to setup single restconf_conn. - * when this is closed, new connect is made, according to connection-type. - */ -typedef struct { - qelem_t rs_qelem; /* List header */ - clicon_handle rs_h; /* Clixon handle */ - char *rs_description; /* Description */ - int rs_callhome; /* 0: listen, 1: callhome */ - int rs_ss; /* Listen: Server socket, ready for accept - * Callhome: connect socket (same as restconf_conn->rc_s) */ - int rs_ssl; /* 0: Not SSL socket, 1:SSL socket */ - char *rs_addrtype; /* Address type according to ietf-inet-types: - eg inet:ipv4-address or inet:ipv6-address */ - char *rs_addrstr; /* Address as string, eg 127.0.0.1, ::1 */ - uint16_t rs_port; /* Protocol port */ - int rs_periodic; /* 0: persistent, 1: periodic (if callhome) */ - uint32_t rs_period; /* Period in s (if callhome & periodic) */ - uint8_t rs_max_attempts; /* max connect attempts (if callhome) */ - uint16_t rs_idle_timeout; /* Max underlying TCP session remains idle (if callhome and periodic) */ - uint64_t rs_start; /* First period start, next is start+periods*period */ - uint64_t rs_period_nr; /* Dynamic succeeding or timed out periods. - Set in restconf_callhome_timer*/ - uint8_t rs_attempts; /* Dynamic connect attempts in this round (if callhome) - * Set in restconf_callhome_cb - */ -} restconf_socket; - +typedef struct restconf_socket restconf_socket; + /* Restconf connection handle * Per connection request */ typedef struct restconf_conn { + qelem_t rc_qelem; /* List header */ /* XXX rc_proto and rc_proto_d1/d2 may not both be necessary. * remove rc_proto? */ + int rc_callhome; /* 0: listen, 1: callhome */ restconf_http_proto rc_proto; /* HTTP protocol: http/1 or http/2 */ int rc_proto_d1; /* parsed version digit 1 */ int rc_proto_d2; /* parsed version digit 2 */ @@ -139,14 +121,47 @@ typedef struct restconf_conn { restconf_socket *rc_socket; /* Backpointer to restconf_socket needed for callhome */ } restconf_conn; +/* Restconf per socket handle + * Two types: listen and callhome. + * Listen: Uses socket rs_ss to listen for connections and accepts them, creates one + * restconf_conn for each new accept. + * Callhome: Calls connect according to timer to setup single restconf_conn. + * when this is closed, new connect is made, according to connection-type. + */ +typedef struct restconf_socket{ + qelem_t rs_qelem; /* List header */ + clicon_handle rs_h; /* Clixon handle */ + char *rs_description; /* Description */ + int rs_callhome; /* 0: listen, 1: callhome */ + int rs_ss; /* Listen: Server socket, ready for accept + * XXXCallhome: connect socket (same as restconf_conn->rc_s) + * Callhome: No-op, see restconf_conn->rc_s + */ + int rs_ssl; /* 0: Not SSL socket, 1:SSL socket */ + char *rs_addrtype; /* Address type according to ietf-inet-types: + eg inet:ipv4-address or inet:ipv6-address */ + char *rs_addrstr; /* Address as string, eg 127.0.0.1, ::1 */ + uint16_t rs_port; /* Protocol port */ + int rs_periodic; /* 0: persistent, 1: periodic (if callhome) */ + uint32_t rs_period; /* Period in s (if callhome & periodic) */ + uint8_t rs_max_attempts; /* max connect attempts (if callhome) */ + uint16_t rs_idle_timeout; /* Max underlying TCP session remains idle (if callhome and periodic) */ + uint64_t rs_start; /* First period start, next is start+periods*period */ + uint64_t rs_period_nr; /* Dynamic succeeding or timed out periods. + Set in restconf_callhome_timer*/ + uint8_t rs_attempts; /* Dynamic connect attempts in this round (if callhome) + * Set in restconf_callhome_cb + */ + restconf_conn *rs_conns; /* List of transient connect sockets */ +} restconf_socket; /* Restconf handle * Global data about ssl (not per packet/request) */ typedef struct { - SSL_CTX *rh_ctx; /* SSL context */ - restconf_socket *rh_sockets; /* List of restconf server (ready for accept) sockets */ - void *rh_arg; /* Packet specific handle */ + SSL_CTX *rn_ctx; /* SSL context */ + restconf_socket *rn_sockets; /* List of restconf server (ready for accept) sockets */ + void *rn_arg; /* Packet specific handle */ } restconf_native_handle; /* @@ -156,17 +171,15 @@ restconf_stream_data *restconf_stream_data_new(restconf_conn *rc, int32_t stream restconf_stream_data *restconf_stream_find(restconf_conn *rc, int32_t id); int restconf_stream_free(restconf_stream_data *sd); restconf_conn *restconf_conn_new(clicon_handle h, int s, restconf_socket *socket); -int restconf_conn_free(restconf_conn *rc); int ssl_x509_name_oneline(SSL *ssl, char **oneline); -int restconf_close_ssl_socket(restconf_conn *rc, int shutdown); /* XXX in restconf_main_native.c */ +int restconf_close_ssl_socket(restconf_conn *rc, const char *callfn, int sslerr0); int restconf_connection_sanity(clicon_handle h, restconf_conn *rc, restconf_stream_data *sd); restconf_native_handle *restconf_native_handle_get(clicon_handle h); int restconf_connection(int s, void *arg); -int restconf_connection_close(clicon_handle h, int s, restconf_socket *rsock); -int restconf_ssl_accept_client(clicon_handle h, int s, restconf_socket *rsock); -int restconf_idle_timer_unreg(restconf_socket *rsock); -int restconf_idle_timer(restconf_socket *rsock); +int restconf_ssl_accept_client(clicon_handle h, int s, restconf_socket *rsock, restconf_conn **rcp); +int restconf_idle_timer_unreg(restconf_conn *rc); +int restconf_idle_timer(restconf_conn *rc); int restconf_callhome_timer_unreg(restconf_socket *rsock); int restconf_callhome_timer(restconf_socket *rsock, int status); int restconf_socket_extract(clicon_handle h, cxobj *xs, cvec *nsc, restconf_socket *rsock, diff --git a/apps/restconf/restconf_nghttp2.c b/apps/restconf/restconf_nghttp2.c index 297b9cb5..65e1b44c 100644 --- a/apps/restconf/restconf_nghttp2.c +++ b/apps/restconf/restconf_nghttp2.c @@ -180,7 +180,7 @@ session_send_callback(nghttp2_session *session, if ((len = SSL_write(rc->rc_ssl, buf+totlen, buflen-totlen)) <= 0){ er = errno; sslerr = SSL_get_error(rc->rc_ssl, len); - clicon_debug(1, "%s errno:%d sslerr:%d", __FUNCTION__, errno, sslerr); + clicon_debug(1, "%s errno:%d sslerr:%d", __FUNCTION__, er, sslerr); switch (sslerr){ case SSL_ERROR_WANT_WRITE: /* 3 */ clicon_debug(1, "%s write SSL_ERROR_WANT_WRITE", __FUNCTION__); @@ -640,11 +640,9 @@ on_stream_close_callback(nghttp2_session *session, // restconf_conn *rc = (restconf_conn *)user_data; clicon_debug(1, "%s %d %s", __FUNCTION__, error_code, nghttp2_strerror(error_code)); -#ifdef NOTNEEDED /* XXX think this is not necessary? */ +#if 0 // NOTNEEDED /* XXX think this is not necessary? */ if (error_code){ - if (restconf_close_ssl_socket(rc, 0) < 0) - return -1; - if (restconf_conn_free(rc) < 0) + if (restconf_close_ssl_socket(rc, __FUNCTION__, 0) < 0) return -1; } #endif diff --git a/include/clixon_custom.h b/include/clixon_custom.h index f10680be..13520381 100644 --- a/include/clixon_custom.h +++ b/include/clixon_custom.h @@ -164,3 +164,18 @@ * This means that text output can not be parsed and loaded. */ #undef TEXT_SYNTAX_NOPREFIX + +/*! Reply with HTTP error when HTTP request on HTTPS socket + * If not set, just close socket and return with TCP reset. + * If set: Incoming request on an SSL socket is known to be non-TLS. + * Problematic part is it is not known it is proper non-TLS HTTP, for that it + * needs parsing/ALPN etc. + * This is the approx algorithm: + * s = accept(); + * ssl = SSL_new() + * if (SSL_accept(ssl) < 0){ + * if (SSL_get_error(ssl, ) == SSL_ERROR_SSL){ + * SSL_free(ssl); + * // Here "s" is still open and you can reply on the non-ssl underlying socket + */ +#define HTTP_ON_HTTPS_REPLY diff --git a/lib/clixon/clixon_err.h b/lib/clixon/clixon_err.h index fd36b8b7..c0bdee30 100644 --- a/lib/clixon/clixon_err.h +++ b/lib/clixon/clixon_err.h @@ -78,7 +78,7 @@ enum clicon_err{ OE_FATAL, /* Fatal error */ OE_UNDEF, /*-- From here error extensions using clixon_err_cat_reg, XXX register dynamically? --*/ - OE_SSL, /* Openssl errors, see eg ssl_get_error */ + OE_SSL, /* Openssl errors, see eg ssl_get_error and clixon_openssl_log_cb */ OE_SNMP , /* Netsnmp error */ OE_NGHTTP2, /* nghttp2 errors, see HAVE_LIBNGHTTP2 */ }; diff --git a/test/test_restconf.sh b/test/test_restconf.sh index e1f8b22f..7a10daad 100755 --- a/test/test_restconf.sh +++ b/test/test_restconf.sh @@ -210,9 +210,9 @@ function testrun() new "Wrong proto=https on http port, expect err 35 wrong version number" expectpart "$(curl $CURLOPTS -X GET https://$addr:80/.well-known/host-meta 2>&1)" 35 #"wrong version number" # dependent on curl version else # see (1) http to https port in restconf_main_native.c - new "Wrong proto=http on https port, expect bad request" - expectpart "$(curl $CURLOPTS -X GET http://$addr:443/.well-known/host-meta 2>&1)" 56 "Connection reset by peer" -# expectpart "$(curl $CURLOPTS -X GET http://$addr:443/.well-known/host-meta)" 0 "HTTP/" "400" + new "Wrong proto=http on https port, expect bad request http1+2" +# expectpart "$(curl $CURLOPTS -X GET http://$addr:443/.well-known/host-meta 2>&1)" 56 "Connection reset by peer" + expectpart "$(curl $CURLOPTS -X GET http://$addr:443/.well-known/host-meta)" 0 "HTTP/" "400" fi @@ -263,7 +263,7 @@ function testrun() new "Wrong proto=https on http port, expect err 35 wrong version number" expectpart "$(curl $CURLOPTS -X GET https://$addr:80/.well-known/host-meta 2>&1)" 35 #"wrong version number" # dependent on curl version else # see (1) http to https port in restconf_main_native.c - new "Wrong proto=http on https port, expect bad request" + new "Wrong proto=http on https port, expect bad request http2-only" expectpart "$(curl $CURLOPTS -X GET http://$addr:443/.well-known/host-meta)" "16 52 55 56" --not-- 'HTTP' fi @@ -304,9 +304,9 @@ function testrun() new "Wrong proto=https on http port, expect err 35 wrong version number" expectpart "$(curl $CURLOPTS -X GET https://$addr:80/.well-known/host-meta 2>&1)" 35 #"wrong version number" # dependent on curl version else # see (1) http to https port in restconf_main_native.c - new "Wrong proto=http on https port, expect bad request" - expectpart "$(curl $CURLOPTS -X GET http://$addr:443/.well-known/host-meta 2>&1)" 56 "Connection reset by peer" -# expectpart "$(curl $CURLOPTS -X GET http://$addr:443/.well-known/host-meta)" 0 "HTTP/" "400" + new "Wrong proto=http on https port, expect bad request http/1 only" +# expectpart "$(curl $CURLOPTS -X GET http://$addr:443/.well-known/host-meta 2>&1)" 56 "Connection reset by peer" + expectpart "$(curl $CURLOPTS -X GET http://$addr:443/.well-known/host-meta)" 0 "HTTP/" "400" fi fi # HTTP/2 diff --git a/test/test_restconf_jukebox.sh b/test/test_restconf_jukebox.sh index 4fef4b51..49613960 100755 --- a/test/test_restconf_jukebox.sh +++ b/test/test_restconf_jukebox.sh @@ -246,12 +246,12 @@ expectpart "$(curl $CURLOPTS -X POST -H 'Content-Type: application/yang-data+jso new 'B.3.5. "insert/point" leaf-list check order (2,4,3,1)' expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/example-jukebox:extra -H 'Accept: application/yang-data+xml')" 0 "HTTP/$HVER 200" '2431' -new "B.2.2. Detect Datastore Resource Entity-Tag Change" # XXX done except entity-changed -new 'B.3.3. "fields" Parameter' -new 'B.3.6. "filter" Parameter' -new 'B.3.7. "start-time" Parameter' -new 'B.3.8. "stop-time" Parameter' -new 'B.3.9. "with-defaults" Parameter' +#new "B.2.2. Detect Datastore Resource Entity-Tag Change" # XXX done except entity-changed +#new 'B.3.3. "fields" Parameter' +#new 'B.3.6. "filter" Parameter' +#new 'B.3.7. "start-time" Parameter' +#new 'B.3.8. "stop-time" Parameter' +#new 'B.3.9. "with-defaults" Parameter' if [ $RC -ne 0 ]; then new "Kill restconf daemon"