Merging upstream version 3.7.1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
35bddb6fe5
commit
3776ec3c2c
26 changed files with 690 additions and 232 deletions
|
@ -57,22 +57,22 @@ set(CMAKE_MACOSX_RPATH TRUE)
|
||||||
# minor version changes with added functionality (new tool, functionality of the tool or library, ...) and
|
# minor version changes with added functionality (new tool, functionality of the tool or library, ...) and
|
||||||
# micro version is changed with a set of small changes or bugfixes anywhere in the project.
|
# micro version is changed with a set of small changes or bugfixes anywhere in the project.
|
||||||
set(LIBNETCONF2_MAJOR_VERSION 3)
|
set(LIBNETCONF2_MAJOR_VERSION 3)
|
||||||
set(LIBNETCONF2_MINOR_VERSION 5)
|
set(LIBNETCONF2_MINOR_VERSION 7)
|
||||||
set(LIBNETCONF2_MICRO_VERSION 5)
|
set(LIBNETCONF2_MICRO_VERSION 1)
|
||||||
set(LIBNETCONF2_VERSION ${LIBNETCONF2_MAJOR_VERSION}.${LIBNETCONF2_MINOR_VERSION}.${LIBNETCONF2_MICRO_VERSION})
|
set(LIBNETCONF2_VERSION ${LIBNETCONF2_MAJOR_VERSION}.${LIBNETCONF2_MINOR_VERSION}.${LIBNETCONF2_MICRO_VERSION})
|
||||||
|
|
||||||
# Version of the library
|
# Version of the library
|
||||||
# Major version is changed with every backward non-compatible API/ABI change in the library, minor version changes
|
# Major version is changed with every backward non-compatible API/ABI change in the library, minor version changes
|
||||||
# with backward compatible change and micro version is connected with any internal change of the library.
|
# with backward compatible change and micro version is connected with any internal change of the library.
|
||||||
set(LIBNETCONF2_MAJOR_SOVERSION 4)
|
set(LIBNETCONF2_MAJOR_SOVERSION 4)
|
||||||
set(LIBNETCONF2_MINOR_SOVERSION 4)
|
set(LIBNETCONF2_MINOR_SOVERSION 6)
|
||||||
set(LIBNETCONF2_MICRO_SOVERSION 5)
|
set(LIBNETCONF2_MICRO_SOVERSION 1)
|
||||||
set(LIBNETCONF2_SOVERSION_FULL ${LIBNETCONF2_MAJOR_SOVERSION}.${LIBNETCONF2_MINOR_SOVERSION}.${LIBNETCONF2_MICRO_SOVERSION})
|
set(LIBNETCONF2_SOVERSION_FULL ${LIBNETCONF2_MAJOR_SOVERSION}.${LIBNETCONF2_MINOR_SOVERSION}.${LIBNETCONF2_MICRO_SOVERSION})
|
||||||
set(LIBNETCONF2_SOVERSION ${LIBNETCONF2_MAJOR_SOVERSION})
|
set(LIBNETCONF2_SOVERSION ${LIBNETCONF2_MAJOR_SOVERSION})
|
||||||
|
|
||||||
# Version of libyang library that this project depends on
|
# Version of libyang library that this project depends on
|
||||||
set(LIBYANG_DEP_VERSION 2.0.0)
|
set(LIBYANG_DEP_VERSION 3.12.0)
|
||||||
set(LIBYANG_DEP_SOVERSION 3.0.0)
|
set(LIBYANG_DEP_SOVERSION 3.9.0)
|
||||||
set(LIBYANG_DEP_SOVERSION_MAJOR 3)
|
set(LIBYANG_DEP_SOVERSION_MAJOR 3)
|
||||||
|
|
||||||
# global C flags
|
# global C flags
|
||||||
|
@ -388,7 +388,7 @@ endif()
|
||||||
|
|
||||||
# generate API/ABI report
|
# generate API/ABI report
|
||||||
if ("${BUILD_TYPE_UPPER}" STREQUAL "ABICHECK")
|
if ("${BUILD_TYPE_UPPER}" STREQUAL "ABICHECK")
|
||||||
lib_abi_check(netconf2 "${headers}" ${LIBNETCONF2_SOVERSION_FULL} 15fbc59efa5e6f1f7bea19ab561d03f8852caabb)
|
lib_abi_check(netconf2 "${headers}" ${LIBNETCONF2_SOVERSION_FULL} 5c72504e9a6fc578ed32fcfb15f59f50d2aab234)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# source files to be covered by the 'format' target and a test with 'format-check' target
|
# source files to be covered by the 'format' target and a test with 'format-check' target
|
||||||
|
|
|
@ -47,7 +47,7 @@ help_print()
|
||||||
" get-config [datastore] [xpath-filter]\t\t send a <get-config> RPC with optional XPath filter and datastore, the default datastore is \"running\" \n\n");
|
" get-config [datastore] [xpath-filter]\t\t send a <get-config> RPC with optional XPath filter and datastore, the default datastore is \"running\" \n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum NC_DATASTORE_TYPE
|
static NC_DATASTORE
|
||||||
string2datastore(const char *str)
|
string2datastore(const char *str)
|
||||||
{
|
{
|
||||||
if (!str) {
|
if (!str) {
|
||||||
|
@ -68,7 +68,7 @@ string2datastore(const char *str)
|
||||||
static int
|
static int
|
||||||
send_rpc(struct nc_session *session, NC_RPC_TYPE rpc_type, const char *param1, const char *param2)
|
send_rpc(struct nc_session *session, NC_RPC_TYPE rpc_type, const char *param1, const char *param2)
|
||||||
{
|
{
|
||||||
enum NC_DATASTORE_TYPE datastore;
|
NC_DATASTORE datastore;
|
||||||
int r = 0, rc = 0;
|
int r = 0, rc = 0;
|
||||||
uint64_t msg_id = 0;
|
uint64_t msg_id = 0;
|
||||||
struct lyd_node *envp = NULL, *op = NULL;
|
struct lyd_node *envp = NULL, *op = NULL;
|
||||||
|
|
|
@ -31,6 +31,10 @@ module libnetconf2-netconf-server {
|
||||||
prefix tlss;
|
prefix tlss;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
revision "2025-01-23" {
|
||||||
|
description "Added a list of YANG modules skipped in the server <hello> message.";
|
||||||
|
}
|
||||||
|
|
||||||
revision "2024-07-09" {
|
revision "2024-07-09" {
|
||||||
description "Second revision.";
|
description "Second revision.";
|
||||||
}
|
}
|
||||||
|
@ -428,11 +432,11 @@ module libnetconf2-netconf-server {
|
||||||
if-feature "ct:certificate-expiration-notification";
|
if-feature "ct:certificate-expiration-notification";
|
||||||
|
|
||||||
description
|
description
|
||||||
"Container for the certificate expiration notification intervals.
|
"Container for the certificate expiration notification intervals. Its child nodes describe the ability to set
|
||||||
Its child nodes describe the ability to set the time intervals for the certificate
|
the time intervals for the certificate expiration notifications. These intervals are given in the form of an
|
||||||
expiration notifications. These intervals are given in the form of an anchor and a period.
|
anchor and a period. By default, these notifications are generated 3, 2, and 1 month; 2 weeks; 7, 6, 5, 4, 3,
|
||||||
By default, these notifications are generated 3, 2, and 1 month; 2 weeks; 7, 6, 5, 4, 3, 2 and 1 day before a certificate expires.
|
2 and 1 day before a certificate expires. Additionally, notifications are generated on the day of expiration
|
||||||
Additionally, notifications are generated on the day of expiration and every day thereafter.
|
and every day thereafter.
|
||||||
|
|
||||||
Simplified example of YANG data that describe the default intervals:
|
Simplified example of YANG data that describe the default intervals:
|
||||||
|
|
||||||
|
@ -471,5 +475,12 @@ module libnetconf2-netconf-server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
leaf-list ignored-hello-module {
|
||||||
|
type string;
|
||||||
|
|
||||||
|
description
|
||||||
|
"List of implemented sysrepo YANG modules that will not be reported the NETCONF server in its <hello> messages.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
6
src/io.c
6
src/io.c
|
@ -38,8 +38,13 @@
|
||||||
#include "netconf.h"
|
#include "netconf.h"
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
#include "session_p.h"
|
#include "session_p.h"
|
||||||
|
|
||||||
|
#ifdef NC_ENABLED_SSH_TLS
|
||||||
|
|
||||||
#include "session_wrapper.h"
|
#include "session_wrapper.h"
|
||||||
|
|
||||||
|
#endif /* NC_ENABLED_SSH_TLS */
|
||||||
|
|
||||||
const char *nc_msgtype2str[] = {
|
const char *nc_msgtype2str[] = {
|
||||||
"error",
|
"error",
|
||||||
"would block",
|
"would block",
|
||||||
|
@ -938,6 +943,7 @@ nc_write_msg_io(struct nc_session *session, int io_timeout, int type, ...)
|
||||||
|
|
||||||
switch (reply->type) {
|
switch (reply->type) {
|
||||||
case NC_RPL_OK:
|
case NC_RPL_OK:
|
||||||
|
assert(rpc_envp != NULL);
|
||||||
if (lyd_new_opaq2(reply_envp, NULL, "ok", NULL, rpc_envp->name.prefix, rpc_envp->name.module_ns, NULL)) {
|
if (lyd_new_opaq2(reply_envp, NULL, "ok", NULL, rpc_envp->name.prefix, rpc_envp->name.module_ns, NULL)) {
|
||||||
lyd_free_tree(reply_envp);
|
lyd_free_tree(reply_envp);
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ nc_libssh_thread_verbosity(int level)
|
||||||
|
|
||||||
#endif /* NC_ENABLED_SSH_TLS */
|
#endif /* NC_ENABLED_SSH_TLS */
|
||||||
|
|
||||||
static void
|
void
|
||||||
nc_log_vprintf(const struct nc_session *session, NC_VERB_LEVEL level, const char *format, va_list args)
|
nc_log_vprintf(const struct nc_session *session, NC_VERB_LEVEL level, const char *format, va_list args)
|
||||||
{
|
{
|
||||||
va_list args2;
|
va_list args2;
|
||||||
|
@ -140,6 +140,7 @@ nc_log_vprintf(const struct nc_session *session, NC_VERB_LEVEL level, const char
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
free(msg);
|
free(msg);
|
||||||
|
va_end(args2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
10
src/log_p.h
10
src/log_p.h
|
@ -35,6 +35,16 @@
|
||||||
*/
|
*/
|
||||||
void nc_log_printf(const struct nc_session *session, NC_VERB_LEVEL level, const char *format, ...);
|
void nc_log_printf(const struct nc_session *session, NC_VERB_LEVEL level, const char *format, ...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Internal printing function with va_list
|
||||||
|
*
|
||||||
|
* @param[in] session Optional NETCONF session that generated the message
|
||||||
|
* @param[in] level Verbose level
|
||||||
|
* @param[in] format Formatting string
|
||||||
|
* @param[in] args va_list with arguments
|
||||||
|
*/
|
||||||
|
void nc_log_vprintf(const struct nc_session *session, NC_VERB_LEVEL level, const char *format, va_list args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Verbose level variable
|
* @brief Verbose level variable
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
/**
|
/**
|
||||||
* @file messages_p.h
|
* @file messages_p.h
|
||||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||||
|
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||||
* @brief libnetconf2's private functions and structures of NETCONF messages.
|
* @brief libnetconf2's private functions and structures of NETCONF messages.
|
||||||
*
|
*
|
||||||
* @copyright
|
* @copyright
|
||||||
* Copyright (c) 2021 CESNET, z.s.p.o.
|
* Copyright (c) 2021 - 2025 CESNET, z.s.p.o.
|
||||||
*
|
*
|
||||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
|
@ -34,7 +35,7 @@ struct nc_server_reply {
|
||||||
|
|
||||||
struct nc_server_reply_data {
|
struct nc_server_reply_data {
|
||||||
NC_RPL type;
|
NC_RPL type;
|
||||||
struct lyd_node *data;
|
struct lyd_node *data; /**< always points to the operation, for both RPCs and actions */
|
||||||
int free;
|
int free;
|
||||||
NC_WD_MODE wd;
|
NC_WD_MODE wd;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* @brief libnetconf2 - server NETCONF messages functions
|
* @brief libnetconf2 - server NETCONF messages functions
|
||||||
*
|
*
|
||||||
* @copyright
|
* @copyright
|
||||||
* Copyright (c) 2015 CESNET, z.s.p.o.
|
* Copyright (c) 2015 - 2025 CESNET, z.s.p.o.
|
||||||
*
|
*
|
||||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
|
@ -261,14 +261,21 @@ nc_err(const struct ly_ctx *ctx, NC_ERR tag, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
struct lyd_node *err = NULL;
|
struct lyd_node *err = NULL;
|
||||||
|
const struct lys_module *nc_mod;
|
||||||
NC_ERR_TYPE type;
|
NC_ERR_TYPE type;
|
||||||
const char *arg1, *arg2;
|
const char *arg1, *arg2;
|
||||||
uint32_t sid;
|
uint32_t sid;
|
||||||
|
|
||||||
NC_CHECK_ARG_RET(NULL, tag, NULL);
|
NC_CHECK_ARG_RET(NULL, tag, ctx, NULL);
|
||||||
|
|
||||||
|
nc_mod = ly_ctx_get_module_implemented(ctx, "ietf-netconf");
|
||||||
|
if (!nc_mod) {
|
||||||
|
ERR(NULL, "Module \"ietf-netconf\" missing in the context.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* rpc-error */
|
/* rpc-error */
|
||||||
if (lyd_new_opaq2(NULL, ctx, "rpc-error", NULL, NULL, NC_NS_BASE, &err)) {
|
if (lyd_new_inner(NULL, nc_mod, "rpc-error", 0, &err)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,17 +344,17 @@ nc_err(const struct ly_ctx *ctx, NC_ERR tag, ...)
|
||||||
ERRARG(NULL, "tag");
|
ERRARG(NULL, "tag");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (lyd_new_opaq2(err, NULL, "error-type", nc_err_type2str(type), NULL, NC_NS_BASE, NULL)) {
|
if (lyd_new_term(err, NULL, "error-type", nc_err_type2str(type), 0, NULL)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* error-tag */
|
/* error-tag */
|
||||||
if (lyd_new_opaq2(err, NULL, "error-tag", nc_err_tag2str(tag), NULL, NC_NS_BASE, NULL)) {
|
if (lyd_new_term(err, NULL, "error-tag", nc_err_tag2str(tag), 0, NULL)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* error-severity */
|
/* error-severity */
|
||||||
if (lyd_new_opaq2(err, NULL, "error-severity", "error", NULL, NC_NS_BASE, NULL)) {
|
if (lyd_new_term(err, NULL, "error-severity", "error", 0, NULL)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,13 +481,17 @@ fail:
|
||||||
API NC_ERR_TYPE
|
API NC_ERR_TYPE
|
||||||
nc_err_get_type(const struct lyd_node *err)
|
nc_err_get_type(const struct lyd_node *err)
|
||||||
{
|
{
|
||||||
struct lyd_node *match;
|
const struct lysc_node *schema;
|
||||||
|
struct lyd_node *match = NULL;
|
||||||
|
|
||||||
NC_CHECK_ARG_RET(NULL, err, 0);
|
NC_CHECK_ARG_RET(NULL, err, 0);
|
||||||
|
|
||||||
lyd_find_sibling_opaq_next(lyd_child(err), "error-type", &match);
|
schema = lys_find_path(NULL, err->schema, "error-type", 0);
|
||||||
|
if (schema) {
|
||||||
|
lyd_find_sibling_val(lyd_child(err), schema, NULL, 0, &match);
|
||||||
|
}
|
||||||
if (match) {
|
if (match) {
|
||||||
return nc_err_str2type(((struct lyd_node_opaq *)match)->value);
|
return nc_err_str2type(lyd_get_value(match));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -489,13 +500,17 @@ nc_err_get_type(const struct lyd_node *err)
|
||||||
API NC_ERR
|
API NC_ERR
|
||||||
nc_err_get_tag(const struct lyd_node *err)
|
nc_err_get_tag(const struct lyd_node *err)
|
||||||
{
|
{
|
||||||
struct lyd_node *match;
|
const struct lysc_node *schema;
|
||||||
|
struct lyd_node *match = NULL;
|
||||||
|
|
||||||
NC_CHECK_ARG_RET(NULL, err, 0);
|
NC_CHECK_ARG_RET(NULL, err, 0);
|
||||||
|
|
||||||
lyd_find_sibling_opaq_next(lyd_child(err), "error-tag", &match);
|
schema = lys_find_path(NULL, err->schema, "error-tag", 0);
|
||||||
|
if (schema) {
|
||||||
|
lyd_find_sibling_val(lyd_child(err), schema, NULL, 0, &match);
|
||||||
|
}
|
||||||
if (match) {
|
if (match) {
|
||||||
return nc_err_str2tag(((struct lyd_node_opaq *)match)->value);
|
return nc_err_str2tag(lyd_get_value(match));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -504,17 +519,25 @@ nc_err_get_tag(const struct lyd_node *err)
|
||||||
API int
|
API int
|
||||||
nc_err_set_app_tag(struct lyd_node *err, const char *error_app_tag)
|
nc_err_set_app_tag(struct lyd_node *err, const char *error_app_tag)
|
||||||
{
|
{
|
||||||
|
const struct lysc_node *schema;
|
||||||
struct lyd_node *match;
|
struct lyd_node *match;
|
||||||
|
|
||||||
NC_CHECK_ARG_RET(NULL, err, error_app_tag, -1);
|
NC_CHECK_ARG_RET(NULL, err, error_app_tag, -1);
|
||||||
|
|
||||||
|
/* find the schema node */
|
||||||
|
schema = lys_find_path(NULL, err->schema, "error-app-tag", 0);
|
||||||
|
if (!schema) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* remove previous node */
|
/* remove previous node */
|
||||||
lyd_find_sibling_opaq_next(lyd_child(err), "error-app-tag", &match);
|
lyd_find_sibling_val(lyd_child(err), schema, NULL, 0, &match);
|
||||||
if (match) {
|
if (match) {
|
||||||
lyd_free_tree(match);
|
lyd_free_tree(match);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lyd_new_opaq2(err, NULL, "error-app-tag", error_app_tag, NULL, NC_NS_BASE, NULL)) {
|
/* create the node */
|
||||||
|
if (lyd_new_term(err, NULL, "error-app-tag", error_app_tag, 0, &match)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,13 +547,17 @@ nc_err_set_app_tag(struct lyd_node *err, const char *error_app_tag)
|
||||||
API const char *
|
API const char *
|
||||||
nc_err_get_app_tag(const struct lyd_node *err)
|
nc_err_get_app_tag(const struct lyd_node *err)
|
||||||
{
|
{
|
||||||
struct lyd_node *match;
|
const struct lysc_node *schema;
|
||||||
|
struct lyd_node *match = NULL;
|
||||||
|
|
||||||
NC_CHECK_ARG_RET(NULL, err, NULL);
|
NC_CHECK_ARG_RET(NULL, err, NULL);
|
||||||
|
|
||||||
lyd_find_sibling_opaq_next(lyd_child(err), "error-app-tag", &match);
|
schema = lys_find_path(NULL, err->schema, "error-tag", 0);
|
||||||
|
if (schema) {
|
||||||
|
lyd_find_sibling_val(lyd_child(err), schema, NULL, 0, &match);
|
||||||
|
}
|
||||||
if (match) {
|
if (match) {
|
||||||
return ((struct lyd_node_opaq *)match)->value;
|
return lyd_get_value(match);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -539,17 +566,25 @@ nc_err_get_app_tag(const struct lyd_node *err)
|
||||||
API int
|
API int
|
||||||
nc_err_set_path(struct lyd_node *err, const char *error_path)
|
nc_err_set_path(struct lyd_node *err, const char *error_path)
|
||||||
{
|
{
|
||||||
|
const struct lysc_node *schema;
|
||||||
struct lyd_node *match;
|
struct lyd_node *match;
|
||||||
|
|
||||||
NC_CHECK_ARG_RET(NULL, err, error_path, -1);
|
NC_CHECK_ARG_RET(NULL, err, error_path, -1);
|
||||||
|
|
||||||
|
/* find the schema node */
|
||||||
|
schema = lys_find_path(NULL, err->schema, "error-path", 0);
|
||||||
|
if (!schema) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* remove previous node */
|
/* remove previous node */
|
||||||
lyd_find_sibling_opaq_next(lyd_child(err), "error-path", &match);
|
lyd_find_sibling_val(lyd_child(err), schema, NULL, 0, &match);
|
||||||
if (match) {
|
if (match) {
|
||||||
lyd_free_tree(match);
|
lyd_free_tree(match);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lyd_new_opaq2(err, NULL, "error-path", error_path, NULL, NC_NS_BASE, NULL)) {
|
/* create the node */
|
||||||
|
if (lyd_new_term(err, NULL, "error-path", error_path, 0, &match)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,13 +594,17 @@ nc_err_set_path(struct lyd_node *err, const char *error_path)
|
||||||
API const char *
|
API const char *
|
||||||
nc_err_get_path(const struct lyd_node *err)
|
nc_err_get_path(const struct lyd_node *err)
|
||||||
{
|
{
|
||||||
struct lyd_node *match;
|
const struct lysc_node *schema;
|
||||||
|
struct lyd_node *match = NULL;
|
||||||
|
|
||||||
NC_CHECK_ARG_RET(NULL, err, NULL);
|
NC_CHECK_ARG_RET(NULL, err, NULL);
|
||||||
|
|
||||||
lyd_find_sibling_opaq_next(lyd_child(err), "error-path", &match);
|
schema = lys_find_path(NULL, err->schema, "error-path", 0);
|
||||||
|
if (schema) {
|
||||||
|
lyd_find_sibling_val(lyd_child(err), schema, NULL, 0, &match);
|
||||||
|
}
|
||||||
if (match) {
|
if (match) {
|
||||||
return ((struct lyd_node_opaq *)match)->value;
|
return lyd_get_value(match);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -574,21 +613,37 @@ nc_err_get_path(const struct lyd_node *err)
|
||||||
API int
|
API int
|
||||||
nc_err_set_msg(struct lyd_node *err, const char *error_message, const char *lang)
|
nc_err_set_msg(struct lyd_node *err, const char *error_message, const char *lang)
|
||||||
{
|
{
|
||||||
struct lyd_node *match;
|
struct lyd_node *match, *prev_anchor;
|
||||||
struct lyd_attr *attr;
|
struct lyd_attr *attr;
|
||||||
|
|
||||||
NC_CHECK_ARG_RET(NULL, err, error_message, -1);
|
NC_CHECK_ARG_RET(NULL, err, error_message, -1);
|
||||||
|
|
||||||
|
/* remove previous node */
|
||||||
lyd_find_sibling_opaq_next(lyd_child(err), "error-message", &match);
|
lyd_find_sibling_opaq_next(lyd_child(err), "error-message", &match);
|
||||||
if (match) {
|
if (match) {
|
||||||
/* Change the value of error-message and keep order of elements to comply with appendix-B in RFC 6241. */
|
lyd_free_tree(match);
|
||||||
lydict_remove(LYD_CTX(err), ((struct lyd_node_opaq *)match)->value);
|
|
||||||
lydict_insert(LYD_CTX(err), error_message, 0, &(((struct lyd_node_opaq *)match)->value));
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* find the previous node anchor (last non-opaque node) */
|
||||||
|
prev_anchor = lyd_child(err);
|
||||||
|
while (prev_anchor && prev_anchor->next && prev_anchor->next->schema) {
|
||||||
|
prev_anchor = prev_anchor->next;
|
||||||
|
}
|
||||||
|
if (!prev_anchor->schema) {
|
||||||
|
prev_anchor = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create the node at the right place */
|
||||||
if (lyd_new_opaq2(err, NULL, "error-message", error_message, NULL, NC_NS_BASE, &match)) {
|
if (lyd_new_opaq2(err, NULL, "error-message", error_message, NULL, NC_NS_BASE, &match)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (prev_anchor) {
|
||||||
|
lyd_insert_after(prev_anchor, match);
|
||||||
|
} else if (match->prev != match) {
|
||||||
|
/* some opaque nodes existed, this must be the first */
|
||||||
|
lyd_insert_before(lyd_child(err), match);
|
||||||
|
}
|
||||||
|
|
||||||
if (lang && lyd_new_attr(match, NULL, "xml:lang", lang, &attr)) {
|
if (lang && lyd_new_attr(match, NULL, "xml:lang", lang, &attr)) {
|
||||||
lyd_free_tree(match);
|
lyd_free_tree(match);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -733,6 +788,16 @@ nc_server_rpc_free(struct nc_server_rpc *rpc)
|
||||||
free(rpc);
|
free(rpc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
API NC_RPL
|
||||||
|
nc_server_reply_type(struct nc_server_reply *reply)
|
||||||
|
{
|
||||||
|
if (!reply) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reply->type;
|
||||||
|
}
|
||||||
|
|
||||||
API void
|
API void
|
||||||
nc_server_reply_free(struct nc_server_reply *reply)
|
nc_server_reply_free(struct nc_server_reply *reply)
|
||||||
{
|
{
|
||||||
|
@ -747,7 +812,7 @@ nc_server_reply_free(struct nc_server_reply *reply)
|
||||||
case NC_RPL_DATA:
|
case NC_RPL_DATA:
|
||||||
data_rpl = (struct nc_server_reply_data *)reply;
|
data_rpl = (struct nc_server_reply_data *)reply;
|
||||||
if (data_rpl->free) {
|
if (data_rpl->free) {
|
||||||
lyd_free_siblings(data_rpl->data);
|
lyd_free_all(data_rpl->data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NC_RPL_OK:
|
case NC_RPL_OK:
|
||||||
|
@ -766,7 +831,7 @@ nc_server_reply_free(struct nc_server_reply *reply)
|
||||||
API struct nc_server_notif *
|
API struct nc_server_notif *
|
||||||
nc_server_notif_new(struct lyd_node *event, char *eventtime, NC_PARAMTYPE paramtype)
|
nc_server_notif_new(struct lyd_node *event, char *eventtime, NC_PARAMTYPE paramtype)
|
||||||
{
|
{
|
||||||
struct nc_server_notif *ntf;
|
struct nc_server_notif *ntf = NULL;
|
||||||
struct lyd_node *elem;
|
struct lyd_node *elem;
|
||||||
int found;
|
int found;
|
||||||
|
|
||||||
|
@ -791,9 +856,10 @@ nc_server_notif_new(struct lyd_node *event, char *eventtime, NC_PARAMTYPE paramt
|
||||||
|
|
||||||
if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
|
if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
|
||||||
ntf->eventtime = strdup(eventtime);
|
ntf->eventtime = strdup(eventtime);
|
||||||
|
NC_CHECK_ERRMEM_GOTO(!ntf->eventtime, , error);
|
||||||
|
|
||||||
if (lyd_dup_single(event, NULL, LYD_DUP_RECURSIVE, &ntf->ntf)) {
|
if (lyd_dup_single(event, NULL, LYD_DUP_RECURSIVE, &ntf->ntf)) {
|
||||||
free(ntf);
|
goto error;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ntf->eventtime = eventtime;
|
ntf->eventtime = eventtime;
|
||||||
|
@ -802,6 +868,11 @@ nc_server_notif_new(struct lyd_node *event, char *eventtime, NC_PARAMTYPE paramt
|
||||||
ntf->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
|
ntf->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
|
||||||
|
|
||||||
return ntf;
|
return ntf;
|
||||||
|
|
||||||
|
error:
|
||||||
|
free(ntf->eventtime);
|
||||||
|
free(ntf);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
API void
|
API void
|
||||||
|
|
|
@ -210,7 +210,7 @@ const char *nc_err_get_app_tag(const struct lyd_node *err);
|
||||||
* @brief Set the \<error-path\> element of an error. Any previous value will be overwritten.
|
* @brief Set the \<error-path\> element of an error. Any previous value will be overwritten.
|
||||||
*
|
*
|
||||||
* @param[in] err Error opaque data node tree to modify.
|
* @param[in] err Error opaque data node tree to modify.
|
||||||
* @param[in] error_path New value of \<error-path\>.
|
* @param[in] error_path New value of \<error-path\> in JSON format.
|
||||||
* @return 0 on success, -1 on error.
|
* @return 0 on success, -1 on error.
|
||||||
*/
|
*/
|
||||||
int nc_err_set_path(struct lyd_node *err, const char *error_path);
|
int nc_err_set_path(struct lyd_node *err, const char *error_path);
|
||||||
|
@ -286,6 +286,14 @@ int nc_err_add_bad_ns(struct lyd_node *err, const char *ns_name);
|
||||||
*/
|
*/
|
||||||
int nc_err_add_info_other(struct lyd_node *err, struct lyd_node *other);
|
int nc_err_add_info_other(struct lyd_node *err, struct lyd_node *other);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get server reply message type.
|
||||||
|
*
|
||||||
|
* @param[in] reply Server rpc-reply object to analyze.
|
||||||
|
* @return Reply type.
|
||||||
|
*/
|
||||||
|
NC_RPL nc_server_reply_type(struct nc_server_reply *reply);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Free a server rpc-reply object.
|
* @brief Free a server rpc-reply object.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
/**
|
/**
|
||||||
* @file netconf.h
|
* @file netconf.h
|
||||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||||
|
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||||
* @brief libnetconf2's general public functions and structures definitions.
|
* @brief libnetconf2's general public functions and structures definitions.
|
||||||
*
|
*
|
||||||
* @copyright
|
* @copyright
|
||||||
* Copyright (c) 2015 - 2021 CESNET, z.s.p.o.
|
* Copyright (c) 2015 - 2025 CESNET, z.s.p.o.
|
||||||
*
|
*
|
||||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||||
* You may not use this file except in compliance with the License.
|
* You may not use this file except in compliance with the License.
|
||||||
|
@ -51,7 +52,7 @@ extern "C" {
|
||||||
/**
|
/**
|
||||||
* @brief Enumeration of reasons of the NETCONF session termination as defined in RFC 6470.
|
* @brief Enumeration of reasons of the NETCONF session termination as defined in RFC 6470.
|
||||||
*/
|
*/
|
||||||
typedef enum NC_SESSION_TERM_REASON {
|
typedef enum {
|
||||||
NC_SESSION_TERM_ERR = -1, /**< error return code for function getting the session termination reason */
|
NC_SESSION_TERM_ERR = -1, /**< error return code for function getting the session termination reason */
|
||||||
NC_SESSION_TERM_NONE = 0, /**< session still running */
|
NC_SESSION_TERM_NONE = 0, /**< session still running */
|
||||||
NC_SESSION_TERM_CLOSED, /**< closed by client in a normal fashion */
|
NC_SESSION_TERM_CLOSED, /**< closed by client in a normal fashion */
|
||||||
|
@ -65,7 +66,7 @@ typedef enum NC_SESSION_TERM_REASON {
|
||||||
/**
|
/**
|
||||||
* @brief Enumeration of NETCONF message types.
|
* @brief Enumeration of NETCONF message types.
|
||||||
*/
|
*/
|
||||||
typedef enum NC_MSG_TYPE {
|
typedef enum {
|
||||||
NC_MSG_ERROR, /**< error return value */
|
NC_MSG_ERROR, /**< error return value */
|
||||||
NC_MSG_WOULDBLOCK, /**< timeout return value */
|
NC_MSG_WOULDBLOCK, /**< timeout return value */
|
||||||
NC_MSG_NONE, /**< no message at input or message was processed internally */
|
NC_MSG_NONE, /**< no message at input or message was processed internally */
|
||||||
|
@ -85,7 +86,7 @@ extern const char *nc_msgtype2str[];
|
||||||
/**
|
/**
|
||||||
* @brief Enumeration of the supported types of datastores defined by NETCONF
|
* @brief Enumeration of the supported types of datastores defined by NETCONF
|
||||||
*/
|
*/
|
||||||
typedef enum NC_DATASTORE_TYPE {
|
typedef enum {
|
||||||
NC_DATASTORE_ERROR = 0, /**< error state of functions returning the datastore type */
|
NC_DATASTORE_ERROR = 0, /**< error state of functions returning the datastore type */
|
||||||
NC_DATASTORE_CONFIG, /**< value describing that the datastore is set as config */
|
NC_DATASTORE_CONFIG, /**< value describing that the datastore is set as config */
|
||||||
NC_DATASTORE_URL, /**< value describing that the datastore data should be given from the URL */
|
NC_DATASTORE_URL, /**< value describing that the datastore data should be given from the URL */
|
||||||
|
@ -97,7 +98,7 @@ typedef enum NC_DATASTORE_TYPE {
|
||||||
/**
|
/**
|
||||||
* @brief Enumeration of NETCONF with-defaults capability modes.
|
* @brief Enumeration of NETCONF with-defaults capability modes.
|
||||||
*/
|
*/
|
||||||
typedef enum NC_WITHDEFAULTS_MODE {
|
typedef enum {
|
||||||
NC_WD_UNKNOWN = 0, /**< invalid mode */
|
NC_WD_UNKNOWN = 0, /**< invalid mode */
|
||||||
NC_WD_ALL, /**< report-all mode */
|
NC_WD_ALL, /**< report-all mode */
|
||||||
NC_WD_ALL_TAG, /**< report-all-tagged mode */
|
NC_WD_ALL_TAG, /**< report-all-tagged mode */
|
||||||
|
@ -108,7 +109,7 @@ typedef enum NC_WITHDEFAULTS_MODE {
|
||||||
/**
|
/**
|
||||||
* @brief Enumeration of NETCONF (both server and client) rpc-reply types.
|
* @brief Enumeration of NETCONF (both server and client) rpc-reply types.
|
||||||
*/
|
*/
|
||||||
typedef enum NC_REPLY {
|
typedef enum {
|
||||||
NC_RPL_OK, /**< OK rpc-reply */
|
NC_RPL_OK, /**< OK rpc-reply */
|
||||||
NC_RPL_DATA, /**< DATA rpc-reply */
|
NC_RPL_DATA, /**< DATA rpc-reply */
|
||||||
NC_RPL_ERROR, /**< ERROR rpc-reply */
|
NC_RPL_ERROR, /**< ERROR rpc-reply */
|
||||||
|
@ -118,7 +119,7 @@ typedef enum NC_REPLY {
|
||||||
/**
|
/**
|
||||||
* @brief Enumeration of function parameter treatments.
|
* @brief Enumeration of function parameter treatments.
|
||||||
*/
|
*/
|
||||||
typedef enum NC_PARAMTYPE {
|
typedef enum {
|
||||||
NC_PARAMTYPE_CONST, /**< use the parameter directly, do not free */
|
NC_PARAMTYPE_CONST, /**< use the parameter directly, do not free */
|
||||||
NC_PARAMTYPE_FREE, /**< use the parameter directly, free afterwards */
|
NC_PARAMTYPE_FREE, /**< use the parameter directly, free afterwards */
|
||||||
NC_PARAMTYPE_DUP_AND_FREE /**< make a copy of the argument, free afterwards */
|
NC_PARAMTYPE_DUP_AND_FREE /**< make a copy of the argument, free afterwards */
|
||||||
|
|
|
@ -2617,6 +2617,14 @@ nc_server_config_encryption_alg(const struct lyd_node *node, enum nc_operation o
|
||||||
|
|
||||||
/* get the algorithm name and append it to supported algs */
|
/* get the algorithm name and append it to supported algs */
|
||||||
alg = ((struct lyd_node_term *)node)->value.ident->name;
|
alg = ((struct lyd_node_term *)node)->value.ident->name;
|
||||||
|
|
||||||
|
/* YANG IDs cannot begin with a number, need to convert them to the correct form */
|
||||||
|
if (!strcmp(alg, "triple-des-cbc")) {
|
||||||
|
alg = "3des-cbc";
|
||||||
|
} else if (!strcmp(alg, "triple-des-ctr")) {
|
||||||
|
alg = "3des-ctr";
|
||||||
|
}
|
||||||
|
|
||||||
if (nc_server_config_transport_params(alg, &opts->encryption_algs, op)) {
|
if (nc_server_config_transport_params(alg, &opts->encryption_algs, op)) {
|
||||||
ret = 1;
|
ret = 1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -3224,7 +3232,7 @@ nc_server_config_create_cert_to_name(const struct lyd_node *node, struct nc_serv
|
||||||
|
|
||||||
assert(!strcmp(LYD_NAME(node), "cert-to-name"));
|
assert(!strcmp(LYD_NAME(node), "cert-to-name"));
|
||||||
|
|
||||||
/* find the list's key */
|
/* find the list's key - ignore result using assert of reference argument instead */
|
||||||
lyd_find_path(node, "id", 0, &n);
|
lyd_find_path(node, "id", 0, &n);
|
||||||
assert(n);
|
assert(n);
|
||||||
id = ((struct lyd_node_term *)n)->value.uint32;
|
id = ((struct lyd_node_term *)n)->value.uint32;
|
||||||
|
@ -4006,13 +4014,20 @@ nc_server_config_parse_netconf_server(const struct lyd_node *node, enum nc_opera
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
nc_server_config_ln2_netconf_server(const struct lyd_node *node, enum nc_operation op)
|
nc_server_config_ln2_netconf_server(const struct lyd_node *UNUSED(node), enum nc_operation op)
|
||||||
{
|
{
|
||||||
(void) node;
|
uint32_t i;
|
||||||
|
|
||||||
assert((op == NC_OP_CREATE) || (op == NC_OP_DELETE));
|
assert((op == NC_OP_CREATE) || (op == NC_OP_DELETE));
|
||||||
|
|
||||||
if (op == NC_OP_DELETE) {
|
if (op == NC_OP_DELETE) {
|
||||||
|
/* delete ignored modules */
|
||||||
|
for (i = 0; i < server_opts.ignored_mod_count; ++i) {
|
||||||
|
free(server_opts.ignored_modules[i]);
|
||||||
|
}
|
||||||
|
free(server_opts.ignored_modules);
|
||||||
|
server_opts.ignored_modules = NULL;
|
||||||
|
server_opts.ignored_mod_count = 0;
|
||||||
|
|
||||||
#ifdef NC_ENABLED_SSH_TLS
|
#ifdef NC_ENABLED_SSH_TLS
|
||||||
/* delete the intervals */
|
/* delete the intervals */
|
||||||
|
@ -4155,6 +4170,45 @@ cleanup:
|
||||||
|
|
||||||
#endif /* NC_ENABLED_SSH_TLS */
|
#endif /* NC_ENABLED_SSH_TLS */
|
||||||
|
|
||||||
|
static int
|
||||||
|
nc_server_config_ignored_module(const struct lyd_node *node, enum nc_operation op)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
const char *mod_name;
|
||||||
|
uint16_t i;
|
||||||
|
|
||||||
|
assert(!strcmp(LYD_NAME(node), "ignored-hello-module"));
|
||||||
|
|
||||||
|
mod_name = lyd_get_value(node);
|
||||||
|
|
||||||
|
if (op == NC_OP_CREATE) {
|
||||||
|
/* add the module */
|
||||||
|
ret = nc_server_config_realloc(mod_name, (void **)&server_opts.ignored_modules,
|
||||||
|
sizeof *server_opts.ignored_modules, &server_opts.ignored_mod_count);
|
||||||
|
} else {
|
||||||
|
/* find the module */
|
||||||
|
for (i = 0; i < server_opts.ignored_mod_count; ++i) {
|
||||||
|
if (!strcmp(server_opts.ignored_modules[i], mod_name)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(i < server_opts.ignored_mod_count);
|
||||||
|
|
||||||
|
/* remove the module by replacing it with the last */
|
||||||
|
free(server_opts.ignored_modules[i]);
|
||||||
|
if (i < server_opts.ignored_mod_count - 1) {
|
||||||
|
server_opts.ignored_modules[i] = server_opts.ignored_modules[server_opts.ignored_mod_count - 1];
|
||||||
|
}
|
||||||
|
--server_opts.ignored_mod_count;
|
||||||
|
if (!server_opts.ignored_mod_count) {
|
||||||
|
free(server_opts.ignored_modules);
|
||||||
|
server_opts.ignored_modules = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nc_server_config_parse_libnetconf2_netconf_server(const struct lyd_node *node, enum nc_operation op)
|
nc_server_config_parse_libnetconf2_netconf_server(const struct lyd_node *node, enum nc_operation op)
|
||||||
{
|
{
|
||||||
|
@ -4169,6 +4223,9 @@ nc_server_config_parse_libnetconf2_netconf_server(const struct lyd_node *node, e
|
||||||
ret = nc_server_config_interval(node, op);
|
ret = nc_server_config_interval(node, op);
|
||||||
}
|
}
|
||||||
#endif /* NC_ENABLED_SSH_TLS */
|
#endif /* NC_ENABLED_SSH_TLS */
|
||||||
|
else if (!strcmp(name, "ignored-hello-module")) {
|
||||||
|
ret = nc_server_config_ignored_module(node, op);
|
||||||
|
}
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ERR(NULL, "Configuring node \"%s\" failed.", LYD_NAME(node));
|
ERR(NULL, "Configuring node \"%s\" failed.", LYD_NAME(node));
|
||||||
|
|
|
@ -29,8 +29,13 @@
|
||||||
#include "log_p.h"
|
#include "log_p.h"
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
#include "session_p.h"
|
#include "session_p.h"
|
||||||
|
|
||||||
|
#ifdef NC_ENABLED_SSH_TLS
|
||||||
|
|
||||||
#include "session_wrapper.h"
|
#include "session_wrapper.h"
|
||||||
|
|
||||||
|
#endif /* NC_ENABLED_SSH_TLS */
|
||||||
|
|
||||||
int
|
int
|
||||||
nc_server_config_create(const struct ly_ctx *ctx, struct lyd_node **tree, const char *value, const char *path_fmt, ...)
|
nc_server_config_create(const struct ly_ctx *ctx, struct lyd_node **tree, const char *value, const char *path_fmt, ...)
|
||||||
{
|
{
|
||||||
|
|
|
@ -498,11 +498,18 @@ _nc_server_config_add_ssh_user_password(const struct ly_ctx *ctx, const char *tr
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
char *hashed_pw = NULL;
|
char *hashed_pw = NULL;
|
||||||
const char *salt = "$6$idsizuippipk$";
|
const char *salt = "$6$idsizuippipk$";
|
||||||
struct crypt_data cdata = {0};
|
struct crypt_data *cdata = NULL;
|
||||||
|
|
||||||
NC_CHECK_ARG_RET(NULL, ctx, tree_path, password, config, 1);
|
NC_CHECK_ARG_RET(NULL, ctx, tree_path, password, config, 1);
|
||||||
|
|
||||||
hashed_pw = crypt_r(password, salt, &cdata);
|
cdata = (struct crypt_data *) calloc(sizeof(struct crypt_data), 1);
|
||||||
|
if (cdata == NULL) {
|
||||||
|
ERR(NULL, "Allocation of crypt_data struct failed.");
|
||||||
|
ret = 1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashed_pw = crypt_r(password, salt, cdata);
|
||||||
if (!hashed_pw) {
|
if (!hashed_pw) {
|
||||||
ERR(NULL, "Hashing password failed (%s).", strerror(errno));
|
ERR(NULL, "Hashing password failed (%s).", strerror(errno));
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
@ -515,6 +522,7 @@ _nc_server_config_add_ssh_user_password(const struct ly_ctx *ctx, const char *tr
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
free(cdata);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,10 @@
|
||||||
|
|
||||||
#ifdef NC_ENABLED_SSH_TLS
|
#ifdef NC_ENABLED_SSH_TLS
|
||||||
|
|
||||||
|
#include "session_wrapper.h"
|
||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include "session_wrapper.h"
|
|
||||||
|
|
||||||
#endif /* NC_ENABLED_SSH_TLS */
|
#endif /* NC_ENABLED_SSH_TLS */
|
||||||
|
|
||||||
|
@ -880,8 +881,25 @@ nc_session_free(struct nc_session *session, void (*data_free)(void *))
|
||||||
struct ly_in *msg;
|
struct ly_in *msg;
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
void *p;
|
void *p;
|
||||||
|
NC_STATUS status;
|
||||||
|
|
||||||
if (!session || (session->status == NC_STATUS_CLOSING)) {
|
if (!session) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((session->side == NC_SERVER) && (session->flags & NC_SESSION_CALLHOME)) {
|
||||||
|
/* CH LOCK */
|
||||||
|
pthread_mutex_lock(&session->opts.server.ch_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = session->status;
|
||||||
|
|
||||||
|
if ((session->side == NC_SERVER) && (session->flags & NC_SESSION_CALLHOME)) {
|
||||||
|
/* CH UNLOCK */
|
||||||
|
pthread_mutex_unlock(&session->opts.server.ch_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == NC_STATUS_CLOSING) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -948,7 +966,7 @@ nc_session_free(struct nc_session *session, void (*data_free)(void *))
|
||||||
nc_session_client_msgs_unlock(session, __func__);
|
nc_session_client_msgs_unlock(session, __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session->status == NC_STATUS_RUNNING) {
|
if ((session->status == NC_STATUS_RUNNING) && nc_session_is_connected(session)) {
|
||||||
/* receive any leftover messages */
|
/* receive any leftover messages */
|
||||||
while (nc_read_msg_poll_io(session, 0, &msg) == 1) {
|
while (nc_read_msg_poll_io(session, 0, &msg) == 1) {
|
||||||
ly_in_free(msg, 1);
|
ly_in_free(msg, 1);
|
||||||
|
@ -1117,8 +1135,6 @@ nc_server_get_cpblts_version(const struct ly_ctx *ctx, LYS_VERSION version)
|
||||||
cpblts[1] = strdup("urn:ietf:params:netconf:base:1.1");
|
cpblts[1] = strdup("urn:ietf:params:netconf:base:1.1");
|
||||||
count = 2;
|
count = 2;
|
||||||
|
|
||||||
/* capabilities */
|
|
||||||
|
|
||||||
mod = ly_ctx_get_module_implemented(ctx, "ietf-netconf");
|
mod = ly_ctx_get_module_implemented(ctx, "ietf-netconf");
|
||||||
if (mod) {
|
if (mod) {
|
||||||
if (lys_feature_value(mod, "writable-running") == LY_SUCCESS) {
|
if (lys_feature_value(mod, "writable-running") == LY_SUCCESS) {
|
||||||
|
@ -1153,11 +1169,15 @@ nc_server_get_cpblts_version(const struct ly_ctx *ctx, LYS_VERSION version)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* HELLO LOCK */
|
||||||
|
pthread_rwlock_rdlock(&server_opts.hello_lock);
|
||||||
|
|
||||||
mod = ly_ctx_get_module_implemented(ctx, "ietf-netconf-with-defaults");
|
mod = ly_ctx_get_module_implemented(ctx, "ietf-netconf-with-defaults");
|
||||||
if (mod) {
|
if (mod) {
|
||||||
wd_basic_mode = ATOMIC_LOAD_RELAXED(server_opts.wd_basic_mode);
|
wd_basic_mode = server_opts.wd_basic_mode;
|
||||||
if (!wd_basic_mode) {
|
if (!wd_basic_mode) {
|
||||||
VRB(NULL, "with-defaults capability will not be advertised even though \"ietf-netconf-with-defaults\" model is present, unknown basic-mode.");
|
VRB(NULL, "with-defaults capability will not be advertised even though \"ietf-netconf-with-defaults\" "
|
||||||
|
"model is present, unknown basic-mode.");
|
||||||
} else {
|
} else {
|
||||||
strcpy(str, "urn:ietf:params:netconf:capability:with-defaults:1.0");
|
strcpy(str, "urn:ietf:params:netconf:capability:with-defaults:1.0");
|
||||||
switch (wd_basic_mode) {
|
switch (wd_basic_mode) {
|
||||||
|
@ -1172,10 +1192,10 @@ nc_server_get_cpblts_version(const struct ly_ctx *ctx, LYS_VERSION version)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERRINT;
|
ERRINT;
|
||||||
break;
|
goto unlock_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
wd_also_supported = ATOMIC_LOAD_RELAXED(server_opts.wd_also_supported);
|
wd_also_supported = server_opts.wd_also_supported;
|
||||||
if (wd_also_supported) {
|
if (wd_also_supported) {
|
||||||
strcat(str, "&also-supported=");
|
strcat(str, "&also-supported=");
|
||||||
if (wd_also_supported & NC_WD_ALL) {
|
if (wd_also_supported & NC_WD_ALL) {
|
||||||
|
@ -1205,10 +1225,15 @@ nc_server_get_cpblts_version(const struct ly_ctx *ctx, LYS_VERSION version)
|
||||||
/* models */
|
/* models */
|
||||||
u = 0;
|
u = 0;
|
||||||
while ((mod = ly_ctx_get_module_iter(ctx, &u))) {
|
while ((mod = ly_ctx_get_module_iter(ctx, &u))) {
|
||||||
|
if (nc_server_is_mod_ignored(mod->name)) {
|
||||||
|
/* ignored, not part of the cababilities */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(mod->name, "ietf-yang-library")) {
|
if (!strcmp(mod->name, "ietf-yang-library")) {
|
||||||
if (!mod->revision || (strcmp(mod->revision, "2016-06-21") && strcmp(mod->revision, "2019-01-04"))) {
|
if (!mod->revision || (strcmp(mod->revision, "2016-06-21") && strcmp(mod->revision, "2019-01-04"))) {
|
||||||
ERR(NULL, "Unknown \"ietf-yang-library\" revision, only 2016-06-21 and 2019-01-04 are supported.");
|
ERR(NULL, "Unknown \"ietf-yang-library\" revision, only 2016-06-21 and 2019-01-04 are supported.");
|
||||||
goto error;
|
goto unlock_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get content-id */
|
/* get content-id */
|
||||||
|
@ -1293,11 +1318,18 @@ nc_server_get_cpblts_version(const struct ly_ctx *ctx, LYS_VERSION version)
|
||||||
add_cpblt(str, &cpblts, &size, &count);
|
add_cpblt(str, &cpblts, &size, &count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* HELLO UNLOCK */
|
||||||
|
pthread_rwlock_unlock(&server_opts.hello_lock);
|
||||||
|
|
||||||
/* ending NULL capability */
|
/* ending NULL capability */
|
||||||
add_cpblt(NULL, &cpblts, &size, &count);
|
add_cpblt(NULL, &cpblts, &size, &count);
|
||||||
|
|
||||||
return cpblts;
|
return cpblts;
|
||||||
|
|
||||||
|
unlock_error:
|
||||||
|
/* HELLO UNLOCK */
|
||||||
|
pthread_rwlock_unlock(&server_opts.hello_lock);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
free(cpblts);
|
free(cpblts);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -1749,7 +1749,7 @@ nc_sock_connect(const char *src_addr, uint16_t src_port, const char *dst_addr, u
|
||||||
hints.ai_protocol = IPPROTO_TCP;
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
i = getaddrinfo(dst_addr, dst_port_str, &hints, &res_list);
|
i = getaddrinfo(dst_addr, dst_port_str, &hints, &res_list);
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
ERR(NULL, "Unable to translate the host address (%s).", gai_strerror(i));
|
ERR(NULL, "Unable to translate the host address \"%s\" (%s).", dst_addr, gai_strerror(i));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2006,6 +2006,10 @@ nc_client_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NC_ENABLED_SSH_TLS
|
#ifdef NC_ENABLED_SSH_TLS
|
||||||
|
if (nc_tls_backend_init_wrap()) {
|
||||||
|
ERR(NULL, "%s: failed to init the SSL library backend.", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (ssh_init()) {
|
if (ssh_init()) {
|
||||||
ERR(NULL, "%s: failed to init libssh.", __func__);
|
ERR(NULL, "%s: failed to init libssh.", __func__);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2024,6 +2028,7 @@ nc_client_destroy(void)
|
||||||
nc_client_ch_del_bind(NULL, 0, 0);
|
nc_client_ch_del_bind(NULL, 0, 0);
|
||||||
nc_client_ssh_destroy_opts();
|
nc_client_ssh_destroy_opts();
|
||||||
nc_client_tls_destroy_opts();
|
nc_client_tls_destroy_opts();
|
||||||
|
nc_tls_backend_destroy_wrap();
|
||||||
ssh_finalize();
|
ssh_finalize();
|
||||||
#endif /* NC_ENABLED_SSH_TLS */
|
#endif /* NC_ENABLED_SSH_TLS */
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,29 +52,79 @@
|
||||||
#include <mbedtls/x509_crt.h>
|
#include <mbedtls/x509_crt.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Converts mbedTLS error codes to a string.
|
* @brief Converts MbedTLS error code to a string and merges it with an arbitrary error message.
|
||||||
*
|
*
|
||||||
* Some mbedTLS functions may return 'high' and some 'low' level errors, try to handle both cases this way.
|
* @param[in] session NETCONF session.
|
||||||
*
|
* @param[in] mbedtls_err_code MbedTLS error code.
|
||||||
* @param[in] err MbedTLS error code.
|
* @param[in] orig_err_msg_fmt Original error message format string.
|
||||||
* @return Error string.
|
* @param[in] ... Additional arguments for the original error message.
|
||||||
*/
|
*/
|
||||||
static const char *
|
static void
|
||||||
nc_get_mbedtls_str_err(int err)
|
nc_mbedtls_strerr(const struct nc_session *session, int mbedtls_err_code, const char *orig_err_msg_fmt, ...)
|
||||||
{
|
{
|
||||||
const char *err_str;
|
va_list args;
|
||||||
|
char *err_buf = NULL, *err_msg_fmt = NULL;
|
||||||
|
size_t err_buf_len = 0, err_msg_fmt_len = 0;
|
||||||
|
const char *high_err_str, *low_err_str;
|
||||||
|
|
||||||
err_str = mbedtls_high_level_strerr(err);
|
va_start(args, orig_err_msg_fmt);
|
||||||
if (err_str) {
|
|
||||||
return err_str;
|
/* get the length of the error strings */
|
||||||
|
high_err_str = mbedtls_high_level_strerr(mbedtls_err_code);
|
||||||
|
low_err_str = mbedtls_low_level_strerr(mbedtls_err_code);
|
||||||
|
if (high_err_str) {
|
||||||
|
err_buf_len += strlen(high_err_str);
|
||||||
|
}
|
||||||
|
if (low_err_str) {
|
||||||
|
err_buf_len += strlen(low_err_str);
|
||||||
|
}
|
||||||
|
if (!err_buf_len) {
|
||||||
|
/* just print the original error message */
|
||||||
|
nc_log_vprintf(session, NC_VERB_ERROR, orig_err_msg_fmt, args);
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
err_str = mbedtls_low_level_strerr(err);
|
if (high_err_str && low_err_str) {
|
||||||
if (err_str) {
|
/* for a colon and 2 spaces */
|
||||||
return err_str;
|
err_buf_len += 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
return "unknown error";
|
/* allocate the mbedtls error buffer */
|
||||||
|
err_buf = malloc(err_buf_len + 1);
|
||||||
|
if (!err_buf) {
|
||||||
|
/* just print the original error message */
|
||||||
|
nc_log_vprintf(session, NC_VERB_ERROR, orig_err_msg_fmt, args);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fill the error buffer and print it */
|
||||||
|
if (high_err_str && low_err_str) {
|
||||||
|
snprintf(err_buf, err_buf_len + 1, "%s : %s", high_err_str, low_err_str);
|
||||||
|
} else if (high_err_str) {
|
||||||
|
snprintf(err_buf, err_buf_len + 1, "%s", high_err_str);
|
||||||
|
} else {
|
||||||
|
snprintf(err_buf, err_buf_len + 1, "%s", low_err_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate the new error format string buffer, err_msg = "orig_err_msg (MbedTLS err)." */
|
||||||
|
err_msg_fmt_len = strlen(orig_err_msg_fmt) + strlen(" (") + strlen(err_buf) + strlen(").");
|
||||||
|
err_msg_fmt = malloc(err_msg_fmt_len + 1);
|
||||||
|
if (!err_msg_fmt) {
|
||||||
|
/* just print the original error message */
|
||||||
|
nc_log_vprintf(session, NC_VERB_ERROR, orig_err_msg_fmt, args);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fill the new error format string */
|
||||||
|
snprintf(err_msg_fmt, err_msg_fmt_len + 1, "%s (%s).", orig_err_msg_fmt, err_buf);
|
||||||
|
|
||||||
|
/* print the error message */
|
||||||
|
nc_log_vprintf(session, NC_VERB_ERROR, err_msg_fmt, args);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
va_end(args);
|
||||||
|
free(err_msg_fmt);
|
||||||
|
free(err_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -100,7 +150,7 @@ nc_server_tls_dn2str(const mbedtls_x509_name *dn)
|
||||||
}
|
}
|
||||||
if (r < 1) {
|
if (r < 1) {
|
||||||
free(str);
|
free(str);
|
||||||
ERR(NULL, "Failed to convert DN to string (%s).", nc_get_mbedtls_str_err(r));
|
nc_mbedtls_strerr(NULL, r, "Failed to convert DN to string");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +182,7 @@ nc_tls_rng_new(mbedtls_ctr_drbg_context **ctr_drbg, mbedtls_entropy_context **en
|
||||||
|
|
||||||
rc = mbedtls_ctr_drbg_seed(*ctr_drbg, mbedtls_entropy_func, *entropy, NULL, 0);
|
rc = mbedtls_ctr_drbg_seed(*ctr_drbg, mbedtls_entropy_func, *entropy, NULL, 0);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Seeding ctr_drbg failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Seeding ctr_drbg failed");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,6 +244,27 @@ nc_tls_get_verify_err_str(int err)
|
||||||
return err_buf;
|
return err_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nc_tls_backend_init_wrap(void)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = psa_crypto_init();
|
||||||
|
|
||||||
|
if (r) {
|
||||||
|
nc_mbedtls_strerr(NULL, r, "Failed to initialize PSA crypto");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nc_tls_backend_destroy_wrap(void)
|
||||||
|
{
|
||||||
|
mbedtls_psa_crypto_free();
|
||||||
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
nc_tls_session_new_wrap(void *tls_cfg)
|
nc_tls_session_new_wrap(void *tls_cfg)
|
||||||
{
|
{
|
||||||
|
@ -207,7 +278,7 @@ nc_tls_session_new_wrap(void *tls_cfg)
|
||||||
|
|
||||||
rc = mbedtls_ssl_setup(session, tls_cfg);
|
rc = mbedtls_ssl_setup(session, tls_cfg);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Setting up TLS session failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Setting up TLS session failed");
|
||||||
mbedtls_ssl_free(session);
|
mbedtls_ssl_free(session);
|
||||||
free(session);
|
free(session);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -335,7 +406,7 @@ nc_tls_pem_to_cert_wrap(const char *cert_data)
|
||||||
|
|
||||||
rc = mbedtls_x509_crt_parse(cert, (const unsigned char *)cert_data, strlen(cert_data) + 1);
|
rc = mbedtls_x509_crt_parse(cert, (const unsigned char *)cert_data, strlen(cert_data) + 1);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Parsing certificate data failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Parsing certificate data failed");
|
||||||
nc_tls_cert_destroy_wrap(cert);
|
nc_tls_cert_destroy_wrap(cert);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -379,7 +450,7 @@ nc_tls_pem_to_privkey_wrap(const char *privkey_data)
|
||||||
|
|
||||||
rc = mbedtls_pk_parse_key(pkey, (const unsigned char *)privkey_data, strlen(privkey_data) + 1, NULL, 0, mbedtls_ctr_drbg_random, ctr_drbg);
|
rc = mbedtls_pk_parse_key(pkey, (const unsigned char *)privkey_data, strlen(privkey_data) + 1, NULL, 0, mbedtls_ctr_drbg_random, ctr_drbg);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Parsing private key data failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Parsing private key data failed");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -755,7 +826,7 @@ nc_server_tls_md5_wrap(void *cert, unsigned char *buf)
|
||||||
|
|
||||||
rc = mbedtls_md5(c->raw.p, c->raw.len, buf);
|
rc = mbedtls_md5(c->raw.p, c->raw.len, buf);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Calculating MD5 digest failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Calculating MD5 digest failed");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -770,7 +841,7 @@ nc_server_tls_sha1_wrap(void *cert, unsigned char *buf)
|
||||||
|
|
||||||
rc = mbedtls_sha1(c->raw.p, c->raw.len, buf);
|
rc = mbedtls_sha1(c->raw.p, c->raw.len, buf);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Calculating SHA-1 digest failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Calculating SHA-1 digest failed");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -785,7 +856,7 @@ nc_server_tls_sha224_wrap(void *cert, unsigned char *buf)
|
||||||
|
|
||||||
rc = mbedtls_sha256(c->raw.p, c->raw.len, buf, 1);
|
rc = mbedtls_sha256(c->raw.p, c->raw.len, buf, 1);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Calculating SHA-224 digest failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Calculating SHA-224 digest failed");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -800,7 +871,7 @@ nc_server_tls_sha256_wrap(void *cert, unsigned char *buf)
|
||||||
|
|
||||||
rc = mbedtls_sha256(c->raw.p, c->raw.len, buf, 0);
|
rc = mbedtls_sha256(c->raw.p, c->raw.len, buf, 0);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Calculating SHA-256 digest failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Calculating SHA-256 digest failed");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -815,7 +886,7 @@ nc_server_tls_sha384_wrap(void *cert, unsigned char *buf)
|
||||||
|
|
||||||
rc = mbedtls_sha512(c->raw.p, c->raw.len, buf, 1);
|
rc = mbedtls_sha512(c->raw.p, c->raw.len, buf, 1);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Calculating SHA-384 digest failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Calculating SHA-384 digest failed");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -830,7 +901,7 @@ nc_server_tls_sha512_wrap(void *cert, unsigned char *buf)
|
||||||
|
|
||||||
rc = mbedtls_sha512(c->raw.p, c->raw.len, buf, 0);
|
rc = mbedtls_sha512(c->raw.p, c->raw.len, buf, 0);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Calculating SHA-512 digest failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Calculating SHA-512 digest failed");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -979,7 +1050,7 @@ nc_tls_import_privkey_file_wrap(const char *privkey_path)
|
||||||
rc = mbedtls_pk_parse_keyfile(pkey, privkey_path, NULL, mbedtls_ctr_drbg_random, ctr_drbg);
|
rc = mbedtls_pk_parse_keyfile(pkey, privkey_path, NULL, mbedtls_ctr_drbg_random, ctr_drbg);
|
||||||
nc_tls_rng_destroy(ctr_drbg, entropy);
|
nc_tls_rng_destroy(ctr_drbg, entropy);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Parsing private key from file \"%s\" failed (%s).", privkey_path, nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Parsing private key from file \"%s\" failed", privkey_path);
|
||||||
nc_tls_privkey_destroy_wrap(pkey);
|
nc_tls_privkey_destroy_wrap(pkey);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1002,7 +1073,7 @@ nc_client_tls_load_cert_key_wrap(const char *cert_path, const char *key_path, vo
|
||||||
|
|
||||||
ret = mbedtls_x509_crt_parse_file(c, cert_path);
|
ret = mbedtls_x509_crt_parse_file(c, cert_path);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ERR(NULL, "Parsing certificate from file \"%s\" failed (%s).", cert_path, nc_get_mbedtls_str_err(ret));
|
nc_mbedtls_strerr(NULL, ret, "Parsing certificate from file \"%s\" failed", cert_path);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1027,12 +1098,12 @@ nc_client_tls_load_trusted_certs_wrap(void *cert_store, const char *file_path, c
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (file_path && ((rc = mbedtls_x509_crt_parse_file(cert_store, file_path)) < 0)) {
|
if (file_path && ((rc = mbedtls_x509_crt_parse_file(cert_store, file_path)) < 0)) {
|
||||||
ERR(NULL, "Loading CA certificate from file \"%s\" failed (%s).", file_path, nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Loading CA certificate from file \"%s\" failed", file_path);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir_path && ((rc = mbedtls_x509_crt_parse_path(cert_store, dir_path)) < 0)) {
|
if (dir_path && ((rc = mbedtls_x509_crt_parse_path(cert_store, dir_path)) < 0)) {
|
||||||
ERR(NULL, "Loading CA certificate from directory \"%s\" failed (%s).", dir_path, nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Loading CA certificate from directory \"%s\" failed", dir_path);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1046,7 +1117,7 @@ nc_client_tls_set_hostname_wrap(void *tls_session, const char *hostname)
|
||||||
|
|
||||||
rc = mbedtls_ssl_set_hostname(tls_session, hostname);
|
rc = mbedtls_ssl_set_hostname(tls_session, hostname);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Setting hostname failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Setting hostname failed");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1083,7 +1154,7 @@ nc_tls_setup_config_from_ctx_wrap(struct nc_tls_ctx *tls_ctx, int side, void *tl
|
||||||
rc = mbedtls_ssl_config_defaults(tls_cfg, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
|
rc = mbedtls_ssl_config_defaults(tls_cfg, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
|
||||||
}
|
}
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Setting default TLS config failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Setting default TLS config failed");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1111,25 +1182,17 @@ nc_tls_verify_error_string_wrap(uint32_t err_code)
|
||||||
void
|
void
|
||||||
nc_client_tls_print_connect_err_wrap(int connect_ret, const char *peername, void *UNUSED(tls_session))
|
nc_client_tls_print_connect_err_wrap(int connect_ret, const char *peername, void *UNUSED(tls_session))
|
||||||
{
|
{
|
||||||
const char *err = nc_get_mbedtls_str_err(connect_ret);
|
if (peername) {
|
||||||
|
nc_mbedtls_strerr(NULL, connect_ret, "TLS connect to host \"%s\" failed", peername);
|
||||||
if (err) {
|
|
||||||
ERR(NULL, "TLS connection to \"%s\" failed (%s).", peername, err);
|
|
||||||
} else {
|
} else {
|
||||||
ERR(NULL, "TLS connection to \"%s\" failed.", peername);
|
nc_mbedtls_strerr(NULL, connect_ret, "TLS connect to an unknown host failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nc_server_tls_print_accept_err_wrap(int accept_ret, void *UNUSED(tls_session))
|
nc_server_tls_print_accept_err_wrap(int accept_ret, void *UNUSED(tls_session))
|
||||||
{
|
{
|
||||||
const char *err = nc_get_mbedtls_str_err(accept_ret);
|
nc_mbedtls_strerr(NULL, accept_ret, "TLS accept failed");
|
||||||
|
|
||||||
if (err) {
|
|
||||||
ERR(NULL, "TLS accept failed (%s).", err);
|
|
||||||
} else {
|
|
||||||
ERR(NULL, "TLS accept failed.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1158,7 +1221,7 @@ nc_base64_decode_wrap(const char *base64, unsigned char **bin)
|
||||||
/* get the size of the decoded data */
|
/* get the size of the decoded data */
|
||||||
rc = mbedtls_base64_decode(NULL, 0, &size, (const unsigned char *)base64, strlen(base64));
|
rc = mbedtls_base64_decode(NULL, 0, &size, (const unsigned char *)base64, strlen(base64));
|
||||||
if (rc != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
|
if (rc != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
|
||||||
ERR(NULL, "Base64 decoding failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Base64 decoding failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1168,7 +1231,7 @@ nc_base64_decode_wrap(const char *base64, unsigned char **bin)
|
||||||
/* decode */
|
/* decode */
|
||||||
rc = mbedtls_base64_decode(*bin, size, &size, (const unsigned char *)base64, strlen(base64));
|
rc = mbedtls_base64_decode(*bin, size, &size, (const unsigned char *)base64, strlen(base64));
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Base64 decoding failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Base64 decoding failed");
|
||||||
free(*bin);
|
free(*bin);
|
||||||
*bin = NULL;
|
*bin = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1185,7 +1248,7 @@ nc_base64_encode_wrap(const unsigned char *bin, size_t len, char **base64)
|
||||||
|
|
||||||
rc = mbedtls_base64_encode(NULL, 0, &size, bin, len);
|
rc = mbedtls_base64_encode(NULL, 0, &size, bin, len);
|
||||||
if (rc != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
|
if (rc != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) {
|
||||||
ERR(NULL, "Base64 encoding failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Base64 encoding failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1194,7 +1257,7 @@ nc_base64_encode_wrap(const unsigned char *bin, size_t len, char **base64)
|
||||||
|
|
||||||
rc = mbedtls_base64_encode((unsigned char *)*base64, size, &size, bin, len);
|
rc = mbedtls_base64_encode((unsigned char *)*base64, size, &size, bin, len);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Base64 encoding failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Base64 encoding failed");
|
||||||
free(*base64);
|
free(*base64);
|
||||||
*base64 = NULL;
|
*base64 = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1217,13 +1280,13 @@ nc_tls_read_wrap(struct nc_session *session, unsigned char *buf, size_t size)
|
||||||
rc = 0;
|
rc = 0;
|
||||||
break;
|
break;
|
||||||
case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
|
case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
|
||||||
ERR(session, "Communication socket unexpectedly closed (MbedTLS).");
|
nc_mbedtls_strerr(session, rc, "Communication socket unexpectedly closed");
|
||||||
session->status = NC_STATUS_INVALID;
|
session->status = NC_STATUS_INVALID;
|
||||||
session->term_reason = NC_SESSION_TERM_DROPPED;
|
session->term_reason = NC_SESSION_TERM_DROPPED;
|
||||||
rc = -1;
|
rc = -1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERR(session, "TLS communication error occurred (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(session, rc, "TLS communication error occurred");
|
||||||
session->status = NC_STATUS_INVALID;
|
session->status = NC_STATUS_INVALID;
|
||||||
session->term_reason = NC_SESSION_TERM_OTHER;
|
session->term_reason = NC_SESSION_TERM_OTHER;
|
||||||
rc = -1;
|
rc = -1;
|
||||||
|
@ -1248,11 +1311,11 @@ nc_tls_write_wrap(struct nc_session *session, const unsigned char *buf, size_t s
|
||||||
rc = 0;
|
rc = 0;
|
||||||
break;
|
break;
|
||||||
case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
|
case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
|
||||||
ERR(session, "TLS connection was properly closed.");
|
nc_mbedtls_strerr(session, rc, "TLS connection was properly closed.");
|
||||||
rc = -1;
|
rc = -1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERR(session, "TLS communication error occurred (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(session, rc, "TLS communication error occurred");
|
||||||
rc = -1;
|
rc = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1281,7 +1344,7 @@ nc_tls_close_notify_wrap(void *tls_session)
|
||||||
while ((rc = mbedtls_ssl_close_notify(tls_session))) {
|
while ((rc = mbedtls_ssl_close_notify(tls_session))) {
|
||||||
if ((rc != MBEDTLS_ERR_SSL_WANT_READ) && (rc != MBEDTLS_ERR_SSL_WANT_WRITE)) {
|
if ((rc != MBEDTLS_ERR_SSL_WANT_READ) && (rc != MBEDTLS_ERR_SSL_WANT_WRITE)) {
|
||||||
/* some error occurred */
|
/* some error occurred */
|
||||||
ERR(NULL, "Sending TLS close notify failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Sending TLS close notify failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1300,7 +1363,7 @@ nc_tls_import_cert_file_wrap(const char *cert_path)
|
||||||
|
|
||||||
rc = mbedtls_x509_crt_parse_file(c, cert_path);
|
rc = mbedtls_x509_crt_parse_file(c, cert_path);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Parsing certificate from file \"%s\" failed (%s).", cert_path, nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Parsing certificate from file \"%s\" failed", cert_path);
|
||||||
nc_tls_cert_destroy_wrap(c);
|
nc_tls_cert_destroy_wrap(c);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1324,7 +1387,7 @@ nc_tls_export_privkey_pem_wrap(void *pkey)
|
||||||
NC_CHECK_ERRMEM_RET(!pem, NULL);
|
NC_CHECK_ERRMEM_RET(!pem, NULL);
|
||||||
}
|
}
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
ERR(NULL, "Exporting private key to PEM format failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Exporting private key to PEM format failed");
|
||||||
free(pem);
|
free(pem);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1369,7 +1432,7 @@ nc_tls_export_pubkey_pem_wrap(void *pkey)
|
||||||
NC_CHECK_ERRMEM_RET(!pem, NULL);
|
NC_CHECK_ERRMEM_RET(!pem, NULL);
|
||||||
}
|
}
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
ERR(NULL, "Exporting public key to PEM format failed (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Exporting public key to PEM format failed");
|
||||||
free(pem);
|
free(pem);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1399,7 +1462,7 @@ nc_tls_get_rsa_pubkey_params_wrap(void *pkey, void **e, void **n)
|
||||||
mbedtls_mpi_init(mod);
|
mbedtls_mpi_init(mod);
|
||||||
|
|
||||||
if ((rc = mbedtls_rsa_export(mbedtls_pk_rsa(*(mbedtls_pk_context *)pkey), mod, NULL, NULL, NULL, exp))) {
|
if ((rc = mbedtls_rsa_export(mbedtls_pk_rsa(*(mbedtls_pk_context *)pkey), mod, NULL, NULL, NULL, exp))) {
|
||||||
ERR(NULL, "Failed to export RSA public key parameters (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Failed to export RSA public key parameters");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1468,7 +1531,7 @@ nc_tls_get_ec_pubkey_params_wrap(void *pkey, void **q, void **q_grp)
|
||||||
/* get the group and public key */
|
/* get the group and public key */
|
||||||
ret = mbedtls_ecp_export(mbedtls_pk_ec(*(mbedtls_pk_context *)pkey), grp, d, p);
|
ret = mbedtls_ecp_export(mbedtls_pk_ec(*(mbedtls_pk_context *)pkey), grp, d, p);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ERR(NULL, "Failed to export EC public key parameters (%s).", nc_get_mbedtls_str_err(ret));
|
nc_mbedtls_strerr(NULL, ret, "Failed to export EC private key parameters");
|
||||||
ret = 1;
|
ret = 1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -1507,7 +1570,7 @@ nc_tls_ec_point_to_bin_wrap(void *q, void *q_grp, unsigned char **bin, int *bin_
|
||||||
NC_CHECK_ERRMEM_RET(!buf, 1);
|
NC_CHECK_ERRMEM_RET(!buf, 1);
|
||||||
}
|
}
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Failed to write EC public key binary (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Failed to write EC public key binary");
|
||||||
free(buf);
|
free(buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1544,7 +1607,7 @@ nc_tls_mpi2bin_wrap(void *mpi, unsigned char **bin, int *bin_len)
|
||||||
|
|
||||||
rc = mbedtls_mpi_write_binary(mpi, buf, buf_len);
|
rc = mbedtls_mpi_write_binary(mpi, buf, buf_len);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Failed to convert MPI to binary (%s).", nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Failed to convert MPI to binary");
|
||||||
free(buf);
|
free(buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1567,7 +1630,7 @@ nc_tls_import_pubkey_file_wrap(const char *pubkey_path)
|
||||||
|
|
||||||
rc = mbedtls_pk_parse_public_keyfile(pk, pubkey_path);
|
rc = mbedtls_pk_parse_public_keyfile(pk, pubkey_path);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ERR(NULL, "Parsing public key from file \"%s\" failed (%s).", pubkey_path, nc_get_mbedtls_str_err(rc));
|
nc_mbedtls_strerr(NULL, rc, "Parsing public key from file \"%s\" failed", pubkey_path);
|
||||||
nc_tls_privkey_destroy_wrap(pk);
|
nc_tls_privkey_destroy_wrap(pk);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1608,7 +1671,7 @@ nc_server_tls_parse_crl_dist_points(unsigned char **p, size_t len, char ***uris,
|
||||||
*/
|
*/
|
||||||
ret = mbedtls_asn1_get_tag(p, end_crl_dist_points, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
ret = mbedtls_asn1_get_tag(p, end_crl_dist_points, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
|
nc_mbedtls_strerr(NULL, ret, "Failed to parse CRL distribution points extension");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if (!len) {
|
if (!len) {
|
||||||
|
@ -1631,7 +1694,7 @@ nc_server_tls_parse_crl_dist_points(unsigned char **p, size_t len, char ***uris,
|
||||||
ERR(NULL, "Failed to parse CRL distribution points extension (nameRelativeToCRLIssuer not yet supported).");
|
ERR(NULL, "Failed to parse CRL distribution points extension (nameRelativeToCRLIssuer not yet supported).");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else {
|
} else {
|
||||||
ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
|
nc_mbedtls_strerr(NULL, ret, "Failed to parse CRL distribution points extension");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1640,7 +1703,7 @@ nc_server_tls_parse_crl_dist_points(unsigned char **p, size_t len, char ***uris,
|
||||||
end_general_names = *p + len;
|
end_general_names = *p + len;
|
||||||
ret = mbedtls_asn1_get_tag(p, end_general_names, &name_len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
ret = mbedtls_asn1_get_tag(p, end_general_names, &name_len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ERR(NULL, "Failed to parse GeneralNames in CRL distribution points extension (%s)", nc_get_mbedtls_str_err(ret));
|
nc_mbedtls_strerr(NULL, ret, "Failed to parse CRL distribution points extension");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1665,8 +1728,7 @@ nc_server_tls_parse_crl_dist_points(unsigned char **p, size_t len, char ***uris,
|
||||||
*/
|
*/
|
||||||
ret = mbedtls_asn1_get_tag(p, end_names, &name_len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | (tag & MBEDTLS_ASN1_CONSTRUCTED) | tag_value);
|
ret = mbedtls_asn1_get_tag(p, end_names, &name_len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | (tag & MBEDTLS_ASN1_CONSTRUCTED) | tag_value);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ERR(NULL, "Failed to parse GeneralName in CRL distribution points extension (%s).",
|
nc_mbedtls_strerr(NULL, ret, "Failed to parse GeneralName in CRL distribution points extension");
|
||||||
nc_get_mbedtls_str_err(ret));
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1699,7 +1761,7 @@ nc_server_tls_parse_crl_dist_points(unsigned char **p, size_t len, char ***uris,
|
||||||
|
|
||||||
} else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
|
} else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
|
||||||
/* failed to parse it, but not because it's optional */
|
/* failed to parse it, but not because it's optional */
|
||||||
ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
|
nc_mbedtls_strerr(NULL, ret, "Failed to parse CRL distribution points extension");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1754,7 +1816,7 @@ nc_server_tls_get_crl_distpoint_uris_wrap(void *leaf_cert, void *cert_store, cha
|
||||||
*/
|
*/
|
||||||
ret = mbedtls_asn1_get_tag(&p, end_v3_ext, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
ret = mbedtls_asn1_get_tag(&p, end_v3_ext, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
|
nc_mbedtls_strerr(NULL, ret, "Failed to parse CRL distribution points extension");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1767,7 +1829,7 @@ nc_server_tls_get_crl_distpoint_uris_wrap(void *leaf_cert, void *cert_store, cha
|
||||||
*/
|
*/
|
||||||
ret = mbedtls_asn1_get_tag(&p, end_v3_ext, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
ret = mbedtls_asn1_get_tag(&p, end_v3_ext, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
|
nc_mbedtls_strerr(NULL, ret, "Failed to parse CRL distribution points extension");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1776,7 +1838,7 @@ nc_server_tls_get_crl_distpoint_uris_wrap(void *leaf_cert, void *cert_store, cha
|
||||||
/* parse extnID */
|
/* parse extnID */
|
||||||
ret = mbedtls_asn1_get_tag(&p, end_ext, &ext_oid.len, MBEDTLS_ASN1_OID);
|
ret = mbedtls_asn1_get_tag(&p, end_ext, &ext_oid.len, MBEDTLS_ASN1_OID);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
|
nc_mbedtls_strerr(NULL, ret, "Failed to parse CRL distribution points extension");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
ext_oid.tag = MBEDTLS_ASN1_OID;
|
ext_oid.tag = MBEDTLS_ASN1_OID;
|
||||||
|
@ -1793,14 +1855,14 @@ nc_server_tls_get_crl_distpoint_uris_wrap(void *leaf_cert, void *cert_store, cha
|
||||||
/* parse optional critical */
|
/* parse optional critical */
|
||||||
ret = mbedtls_asn1_get_bool(&p, end_ext, &is_critical);
|
ret = mbedtls_asn1_get_bool(&p, end_ext, &is_critical);
|
||||||
if (ret && (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) {
|
if (ret && (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) {
|
||||||
ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
|
nc_mbedtls_strerr(NULL, ret, "Failed to parse CRL distribution points extension");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse extnValue */
|
/* parse extnValue */
|
||||||
ret = mbedtls_asn1_get_tag(&p, end_ext, &len, MBEDTLS_ASN1_OCTET_STRING);
|
ret = mbedtls_asn1_get_tag(&p, end_ext, &len, MBEDTLS_ASN1_OCTET_STRING);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
|
nc_mbedtls_strerr(NULL, ret, "Failed to parse CRL distribution points extension");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1813,12 +1875,12 @@ nc_server_tls_get_crl_distpoint_uris_wrap(void *leaf_cert, void *cert_store, cha
|
||||||
*/
|
*/
|
||||||
ret = mbedtls_asn1_get_tag(&p, end_ext_octet, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
ret = mbedtls_asn1_get_tag(&p, end_ext_octet, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
|
nc_mbedtls_strerr(NULL, ret, "Failed to parse CRL distribution points extension");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if (p + len != end_ext_octet) {
|
if (p + len != end_ext_octet) {
|
||||||
/* length mismatch */
|
/* length mismatch */
|
||||||
ERR(NULL, "Failed to parse CRL distribution points extension (%s).", nc_get_mbedtls_str_err(ret));
|
ERR(NULL, "Failed to parse CRL distribution points extension (length mismatch).");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else if (!len) {
|
} else if (!len) {
|
||||||
/* empty sequence, but size is 1..max */
|
/* empty sequence, but size is 1..max */
|
||||||
|
|
|
@ -44,6 +44,20 @@
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
#include <openssl/x509v3.h>
|
#include <openssl/x509v3.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
nc_tls_backend_init_wrap(void)
|
||||||
|
{
|
||||||
|
/* nothing to do */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nc_tls_backend_destroy_wrap(void)
|
||||||
|
{
|
||||||
|
/* nothing to do */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
nc_tls_session_new_wrap(void *tls_cfg)
|
nc_tls_session_new_wrap(void *tls_cfg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,8 +30,13 @@
|
||||||
#include "session_client.h"
|
#include "session_client.h"
|
||||||
#include "session_server.h"
|
#include "session_server.h"
|
||||||
#include "session_server_ch.h"
|
#include "session_server_ch.h"
|
||||||
|
|
||||||
|
#ifdef NC_ENABLED_SSH_TLS
|
||||||
|
|
||||||
#include "session_wrapper.h"
|
#include "session_wrapper.h"
|
||||||
|
|
||||||
|
#endif /* NC_ENABLED_SSH_TLS */
|
||||||
|
|
||||||
extern struct nc_server_opts server_opts;
|
extern struct nc_server_opts server_opts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -498,19 +503,27 @@ struct nc_ch_client_thread_arg {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nc_server_opts {
|
struct nc_server_opts {
|
||||||
/* ACCESS unlocked */
|
/* ACCESS locked - hello lock - separate lock to not always hold config_lock */
|
||||||
ATOMIC_T wd_basic_mode;
|
char **ignored_modules; /**< Names of YANG modules that are not reported in the server <hello> message. */
|
||||||
ATOMIC_T wd_also_supported;
|
uint16_t ignored_mod_count;
|
||||||
uint32_t capabilities_count;
|
NC_WD_MODE wd_basic_mode; /**< With-defaults basic mode of the server. */
|
||||||
|
int wd_also_supported; /**< Bitmap of with-defaults modes that are also supported by the server. */
|
||||||
char **capabilities;
|
char **capabilities;
|
||||||
|
uint32_t capabilities_count;
|
||||||
|
|
||||||
char *(*content_id_clb)(void *user_data);
|
char *(*content_id_clb)(void *user_data); /**< Callback for generating content_id for ietf-yang-library data. */
|
||||||
void *content_id_data;
|
void *content_id_data;
|
||||||
|
|
||||||
void (*content_id_data_free)(void *data);
|
void (*content_id_data_free)(void *data);
|
||||||
|
|
||||||
|
pthread_rwlock_t hello_lock; /**< Needs to be held while the server <hello> message is being generated. */
|
||||||
|
|
||||||
|
/* ACCESS unlocked */
|
||||||
uint16_t idle_timeout;
|
uint16_t idle_timeout;
|
||||||
|
|
||||||
|
/* ACCESS locked - options modified by YANG data/API - WRITE lock
|
||||||
|
* - options read when accepting sessions - READ lock */
|
||||||
|
pthread_rwlock_t config_lock;
|
||||||
|
|
||||||
#ifdef NC_ENABLED_SSH_TLS
|
#ifdef NC_ENABLED_SSH_TLS
|
||||||
char *authkey_path_fmt; /**< Path to users' public keys that may contain tokens with special meaning. */
|
char *authkey_path_fmt; /**< Path to users' public keys that may contain tokens with special meaning. */
|
||||||
char *pam_config_name; /**< PAM configuration file name. */
|
char *pam_config_name; /**< PAM configuration file name. */
|
||||||
|
@ -521,13 +534,12 @@ struct nc_server_opts {
|
||||||
int (*user_verify_clb)(const struct nc_session *session);
|
int (*user_verify_clb)(const struct nc_session *session);
|
||||||
#endif /* NC_ENABLED_SSH_TLS */
|
#endif /* NC_ENABLED_SSH_TLS */
|
||||||
|
|
||||||
pthread_rwlock_t config_lock;
|
|
||||||
|
|
||||||
#ifdef NC_ENABLED_SSH_TLS
|
#ifdef NC_ENABLED_SSH_TLS
|
||||||
struct nc_keystore keystore; /**< store for server's keys/certificates */
|
struct nc_keystore keystore; /**< Server's keys/certificates. */
|
||||||
struct nc_truststore truststore; /**< store for server client's keys/certificates */
|
struct nc_truststore truststore; /**< Server client's keys/certificates. */
|
||||||
#endif /* NC_ENABLED_SSH_TLS */
|
#endif /* NC_ENABLED_SSH_TLS */
|
||||||
|
|
||||||
|
/* ACCESS locked */
|
||||||
struct nc_bind *binds;
|
struct nc_bind *binds;
|
||||||
pthread_mutex_t bind_lock; /**< To avoid concurrent calls of poll and accept on the bound sockets **/
|
pthread_mutex_t bind_lock; /**< To avoid concurrent calls of poll and accept on the bound sockets **/
|
||||||
struct nc_endpt {
|
struct nc_endpt {
|
||||||
|
@ -607,11 +619,12 @@ struct nc_server_opts {
|
||||||
} ch_dispatch_data;
|
} ch_dispatch_data;
|
||||||
#endif /* NC_ENABLED_SSH_TLS */
|
#endif /* NC_ENABLED_SSH_TLS */
|
||||||
|
|
||||||
/* Atomic IDs */
|
/* ACCESS unlocked */
|
||||||
ATOMIC_T new_session_id;
|
ATOMIC_T new_session_id;
|
||||||
ATOMIC_T new_client_id;
|
ATOMIC_T new_client_id;
|
||||||
|
|
||||||
#ifdef NC_ENABLED_SSH_TLS
|
#ifdef NC_ENABLED_SSH_TLS
|
||||||
|
/* ACCESS locked */
|
||||||
struct {
|
struct {
|
||||||
pthread_t tid; /**< Thread ID of the certificate expiration notification thread. */
|
pthread_t tid; /**< Thread ID of the certificate expiration notification thread. */
|
||||||
int thread_running; /**< Flag representing the runningness of the cert exp notification thread. */
|
int thread_running; /**< Flag representing the runningness of the cert exp notification thread. */
|
||||||
|
@ -628,7 +641,8 @@ struct nc_server_opts {
|
||||||
int interval_count; /**< Number of intervals. */
|
int interval_count; /**< Number of intervals. */
|
||||||
} cert_exp_notif;
|
} cert_exp_notif;
|
||||||
|
|
||||||
FILE *tls_keylog_file; /**< File to log TLS secrets to. */
|
/* ACCESS unlocked */
|
||||||
|
FILE *tls_keylog_file; /**< File to log TLS secrets to. */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1238,6 +1252,14 @@ int nc_session_tls_crl_from_cert_ext_fetch(void *leaf_cert, void *cert_store, vo
|
||||||
|
|
||||||
#endif /* NC_ENABLED_SSH_TLS */
|
#endif /* NC_ENABLED_SSH_TLS */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check whether a module is not ignored by the server.
|
||||||
|
*
|
||||||
|
* @param[in] mod_name Module name to check.
|
||||||
|
* @return Whether the module is ignored.
|
||||||
|
*/
|
||||||
|
int nc_server_is_mod_ignored(const char *mod_name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functions
|
* Functions
|
||||||
* - io.c
|
* - io.c
|
||||||
|
|
|
@ -44,14 +44,18 @@
|
||||||
#include "session_p.h"
|
#include "session_p.h"
|
||||||
#include "session_server.h"
|
#include "session_server.h"
|
||||||
#include "session_server_ch.h"
|
#include "session_server_ch.h"
|
||||||
#include "session_wrapper.h"
|
|
||||||
|
|
||||||
#ifdef NC_ENABLED_SSH_TLS
|
#ifdef NC_ENABLED_SSH_TLS
|
||||||
|
|
||||||
|
#include "session_wrapper.h"
|
||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#endif
|
|
||||||
|
#endif /* NC_ENABLED_SSH_TLS */
|
||||||
|
|
||||||
struct nc_server_opts server_opts = {
|
struct nc_server_opts server_opts = {
|
||||||
|
.hello_lock = PTHREAD_RWLOCK_INITIALIZER,
|
||||||
.config_lock = PTHREAD_RWLOCK_INITIALIZER,
|
.config_lock = PTHREAD_RWLOCK_INITIALIZER,
|
||||||
.ch_client_lock = PTHREAD_RWLOCK_INITIALIZER,
|
.ch_client_lock = PTHREAD_RWLOCK_INITIALIZER,
|
||||||
.idle_timeout = 180, /**< default idle timeout (not in config for UNIX socket) */
|
.idle_timeout = 180, /**< default idle timeout (not in config for UNIX socket) */
|
||||||
|
@ -818,41 +822,62 @@ nc_server_keylog_file_open(void)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a rwlock.
|
||||||
|
*
|
||||||
|
* @param[in] rwlock RW lock to initialize.
|
||||||
|
* @return errno.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
nc_server_init_rwlock(pthread_rwlock_t *rwlock)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP
|
||||||
|
int rc = 0;
|
||||||
|
pthread_rwlockattr_t attr;
|
||||||
|
|
||||||
|
if ((rc = pthread_rwlockattr_init(&attr))) {
|
||||||
|
ERR(NULL, "%s: failed to init attribute (%s).", __func__, strerror(rc));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rc = pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP))) {
|
||||||
|
ERR(NULL, "%s: failed to set attribute (%s).", __func__, strerror(rc));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rc = pthread_rwlock_init(rwlock, &attr))) {
|
||||||
|
ERR(NULL, "%s: failed to init rwlock (%s).", __func__, strerror(rc));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
pthread_rwlockattr_destroy(&attr);
|
||||||
|
return rc;
|
||||||
|
#else
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if ((rc = pthread_rwlock_init(rwlock, NULL))) {
|
||||||
|
ERR(NULL, "%s: failed to init rwlock (%s).", __func__, strerror(rc));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
API int
|
API int
|
||||||
nc_server_init(void)
|
nc_server_init(void)
|
||||||
{
|
{
|
||||||
pthread_rwlockattr_t *attr_p = NULL;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
ATOMIC_STORE_RELAXED(server_opts.new_session_id, 1);
|
ATOMIC_STORE_RELAXED(server_opts.new_session_id, 1);
|
||||||
ATOMIC_STORE_RELAXED(server_opts.new_client_id, 1);
|
ATOMIC_STORE_RELAXED(server_opts.new_client_id, 1);
|
||||||
|
|
||||||
#ifdef HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP
|
if (nc_server_init_rwlock(&server_opts.config_lock)) {
|
||||||
pthread_rwlockattr_t attr;
|
|
||||||
|
|
||||||
if ((r = pthread_rwlockattr_init(&attr))) {
|
|
||||||
ERR(NULL, "%s: failed init attribute (%s).", __func__, strerror(r));
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
attr_p = &attr;
|
if (nc_server_init_rwlock(&server_opts.ch_client_lock)) {
|
||||||
if ((r = pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP))) {
|
|
||||||
ERR(NULL, "%s: failed set attribute (%s).", __func__, strerror(r));
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((r = pthread_rwlock_init(&server_opts.config_lock, attr_p))) {
|
|
||||||
ERR(NULL, "%s: failed to init rwlock(%s).", __func__, strerror(r));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if ((r = pthread_rwlock_init(&server_opts.ch_client_lock, attr_p))) {
|
|
||||||
ERR(NULL, "%s: failed to init rwlock(%s).", __func__, strerror(r));
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attr_p) {
|
|
||||||
pthread_rwlockattr_destroy(attr_p);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef NC_ENABLED_SSH_TLS
|
#ifdef NC_ENABLED_SSH_TLS
|
||||||
if (curl_global_init(CURL_GLOBAL_SSL | CURL_GLOBAL_ACK_EINTR)) {
|
if (curl_global_init(CURL_GLOBAL_SSL | CURL_GLOBAL_ACK_EINTR)) {
|
||||||
|
@ -860,6 +885,11 @@ nc_server_init(void)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nc_tls_backend_init_wrap()) {
|
||||||
|
ERR(NULL, "%s: failed to init the SSL library backend.", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* optional for dynamic library, mandatory for static */
|
/* optional for dynamic library, mandatory for static */
|
||||||
if (ssh_init()) {
|
if (ssh_init()) {
|
||||||
ERR(NULL, "%s: failed to init libssh.", __func__);
|
ERR(NULL, "%s: failed to init libssh.", __func__);
|
||||||
|
@ -889,9 +919,6 @@ nc_server_init(void)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (attr_p) {
|
|
||||||
pthread_rwlockattr_destroy(attr_p);
|
|
||||||
}
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -942,6 +969,7 @@ nc_server_destroy(void)
|
||||||
nc_server_config_ks_keystore(NULL, NC_OP_DELETE);
|
nc_server_config_ks_keystore(NULL, NC_OP_DELETE);
|
||||||
nc_server_config_ts_truststore(NULL, NC_OP_DELETE);
|
nc_server_config_ts_truststore(NULL, NC_OP_DELETE);
|
||||||
curl_global_cleanup();
|
curl_global_cleanup();
|
||||||
|
nc_tls_backend_destroy_wrap();
|
||||||
ssh_finalize();
|
ssh_finalize();
|
||||||
|
|
||||||
/* close the TLS keylog file */
|
/* close the TLS keylog file */
|
||||||
|
@ -962,8 +990,15 @@ nc_server_set_capab_withdefaults(NC_WD_MODE basic_mode, int also_supported)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ATOMIC_STORE_RELAXED(server_opts.wd_basic_mode, basic_mode);
|
/* HELLO LOCK */
|
||||||
ATOMIC_STORE_RELAXED(server_opts.wd_also_supported, also_supported);
|
pthread_rwlock_wrlock(&server_opts.hello_lock);
|
||||||
|
|
||||||
|
server_opts.wd_basic_mode = basic_mode;
|
||||||
|
server_opts.wd_also_supported = also_supported;
|
||||||
|
|
||||||
|
/* HELLO UNLOCK */
|
||||||
|
pthread_rwlock_unlock(&server_opts.hello_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -975,12 +1010,18 @@ nc_server_get_capab_withdefaults(NC_WD_MODE *basic_mode, int *also_supported)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* HELLO LOCK */
|
||||||
|
pthread_rwlock_wrlock(&server_opts.hello_lock);
|
||||||
|
|
||||||
if (basic_mode) {
|
if (basic_mode) {
|
||||||
*basic_mode = ATOMIC_LOAD_RELAXED(server_opts.wd_basic_mode);
|
*basic_mode = server_opts.wd_basic_mode;
|
||||||
}
|
}
|
||||||
if (also_supported) {
|
if (also_supported) {
|
||||||
*also_supported = ATOMIC_LOAD_RELAXED(server_opts.wd_also_supported);
|
*also_supported = server_opts.wd_also_supported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* HELLO UNLOCK */
|
||||||
|
pthread_rwlock_unlock(&server_opts.hello_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
API int
|
API int
|
||||||
|
@ -993,6 +1034,9 @@ nc_server_set_capability(const char *value)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* HELLO LOCK */
|
||||||
|
pthread_rwlock_wrlock(&server_opts.hello_lock);
|
||||||
|
|
||||||
mem = realloc(server_opts.capabilities, (server_opts.capabilities_count + 1) * sizeof *server_opts.capabilities);
|
mem = realloc(server_opts.capabilities, (server_opts.capabilities_count + 1) * sizeof *server_opts.capabilities);
|
||||||
NC_CHECK_ERRMEM_RET(!mem, EXIT_FAILURE);
|
NC_CHECK_ERRMEM_RET(!mem, EXIT_FAILURE);
|
||||||
server_opts.capabilities = mem;
|
server_opts.capabilities = mem;
|
||||||
|
@ -1000,6 +1044,9 @@ nc_server_set_capability(const char *value)
|
||||||
server_opts.capabilities[server_opts.capabilities_count] = strdup(value);
|
server_opts.capabilities[server_opts.capabilities_count] = strdup(value);
|
||||||
server_opts.capabilities_count++;
|
server_opts.capabilities_count++;
|
||||||
|
|
||||||
|
/* HELLO UNLOCK */
|
||||||
|
pthread_rwlock_unlock(&server_opts.hello_lock);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1007,9 +1054,15 @@ API void
|
||||||
nc_server_set_content_id_clb(char *(*content_id_clb)(void *user_data), void *user_data,
|
nc_server_set_content_id_clb(char *(*content_id_clb)(void *user_data), void *user_data,
|
||||||
void (*free_user_data)(void *user_data))
|
void (*free_user_data)(void *user_data))
|
||||||
{
|
{
|
||||||
|
/* HELLO LOCK */
|
||||||
|
pthread_rwlock_wrlock(&server_opts.hello_lock);
|
||||||
|
|
||||||
server_opts.content_id_clb = content_id_clb;
|
server_opts.content_id_clb = content_id_clb;
|
||||||
server_opts.content_id_data = user_data;
|
server_opts.content_id_data = user_data;
|
||||||
server_opts.content_id_data_free = free_user_data;
|
server_opts.content_id_data_free = free_user_data;
|
||||||
|
|
||||||
|
/* HELLO UNLOCK */
|
||||||
|
pthread_rwlock_unlock(&server_opts.hello_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
API NC_MSG_TYPE
|
API NC_MSG_TYPE
|
||||||
|
@ -2731,7 +2784,7 @@ nc_connect_ch_endpt(struct nc_ch_endpt *endpt, nc_server_ch_session_acquire_ctx_
|
||||||
const struct ly_ctx *ctx = NULL;
|
const struct ly_ctx *ctx = NULL;
|
||||||
int sock, ret;
|
int sock, ret;
|
||||||
struct timespec ts_cur;
|
struct timespec ts_cur;
|
||||||
char *ip_host;
|
char *ip_host = NULL;
|
||||||
|
|
||||||
sock = nc_sock_connect(endpt->src_addr, endpt->src_port, endpt->dst_addr, endpt->dst_port,
|
sock = nc_sock_connect(endpt->src_addr, endpt->src_port, endpt->dst_addr, endpt->dst_port,
|
||||||
NC_CH_CONNECT_TIMEOUT, &endpt->ka, &endpt->sock_pending, &ip_host);
|
NC_CH_CONNECT_TIMEOUT, &endpt->ka, &endpt->sock_pending, &ip_host);
|
||||||
|
@ -4080,3 +4133,17 @@ nc_server_notif_cert_expiration_thread_stop(int wait)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* NC_ENABLED_SSH_TLS */
|
#endif /* NC_ENABLED_SSH_TLS */
|
||||||
|
|
||||||
|
int
|
||||||
|
nc_server_is_mod_ignored(const char *mod_name)
|
||||||
|
{
|
||||||
|
uint16_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < server_opts.ignored_mod_count; ++i) {
|
||||||
|
if (!strcmp(server_opts.ignored_modules[i], mod_name)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -625,7 +625,8 @@ static int
|
||||||
nc_server_ssh_compare_password(const char *stored_pw, const char *received_pw)
|
nc_server_ssh_compare_password(const char *stored_pw, const char *received_pw)
|
||||||
{
|
{
|
||||||
char *received_pw_hash = NULL;
|
char *received_pw_hash = NULL;
|
||||||
struct crypt_data cdata = {0};
|
struct crypt_data *cdata;
|
||||||
|
int ret;
|
||||||
|
|
||||||
NC_CHECK_ARG_RET(NULL, stored_pw, received_pw, 1);
|
NC_CHECK_ARG_RET(NULL, stored_pw, received_pw, 1);
|
||||||
|
|
||||||
|
@ -645,13 +646,23 @@ nc_server_ssh_compare_password(const char *stored_pw, const char *received_pw)
|
||||||
return strcmp(stored_pw + 3, received_pw);
|
return strcmp(stored_pw + 3, received_pw);
|
||||||
}
|
}
|
||||||
|
|
||||||
received_pw_hash = crypt_r(received_pw, stored_pw, &cdata);
|
cdata = (struct crypt_data *) calloc(sizeof(struct crypt_data), 1);
|
||||||
if (!received_pw_hash) {
|
if (cdata == NULL) {
|
||||||
ERR(NULL, "Hashing the password failed (%s).", strerror(errno));
|
ERR(NULL, "Allocation of crypt_data struct failed.");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return strcmp(received_pw_hash, stored_pw);
|
received_pw_hash = crypt_r(received_pw, stored_pw, cdata);
|
||||||
|
if (!received_pw_hash) {
|
||||||
|
ERR(NULL, "Hashing the password failed (%s).", strerror(errno));
|
||||||
|
free(cdata);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = strcmp(received_pw_hash, stored_pw);
|
||||||
|
free(cdata);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
API int
|
API int
|
||||||
|
@ -1946,17 +1957,29 @@ nc_accept_ssh_session(struct nc_session *session, struct nc_server_ssh_opts *opt
|
||||||
rc = -1;
|
rc = -1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if (opts->encryption_algs && ssh_bind_options_set(sbind, SSH_BIND_OPTIONS_CIPHERS_S_C, opts->encryption_algs)) {
|
if (opts->encryption_algs) {
|
||||||
rc = -1;
|
if (ssh_bind_options_set(sbind, SSH_BIND_OPTIONS_CIPHERS_S_C, opts->encryption_algs)) {
|
||||||
goto cleanup;
|
rc = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (ssh_bind_options_set(sbind, SSH_BIND_OPTIONS_CIPHERS_C_S, opts->encryption_algs)) {
|
||||||
|
rc = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (opts->kex_algs && ssh_bind_options_set(sbind, SSH_BIND_OPTIONS_KEY_EXCHANGE, opts->kex_algs)) {
|
if (opts->kex_algs && ssh_bind_options_set(sbind, SSH_BIND_OPTIONS_KEY_EXCHANGE, opts->kex_algs)) {
|
||||||
rc = -1;
|
rc = -1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if (opts->mac_algs && ssh_bind_options_set(sbind, SSH_BIND_OPTIONS_HMAC_S_C, opts->mac_algs)) {
|
if (opts->mac_algs) {
|
||||||
rc = -1;
|
if (ssh_bind_options_set(sbind, SSH_BIND_OPTIONS_HMAC_S_C, opts->mac_algs)) {
|
||||||
goto cleanup;
|
rc = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (ssh_bind_options_set(sbind, SSH_BIND_OPTIONS_HMAC_C_S, opts->mac_algs)) {
|
||||||
|
rc = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* configure the ssh banner */
|
/* configure the ssh banner */
|
||||||
|
|
|
@ -331,8 +331,8 @@ static int
|
||||||
nc_server_tls_cert_to_name(struct nc_ctn *ctn, void *cert_chain, char **username)
|
nc_server_tls_cert_to_name(struct nc_ctn *ctn, void *cert_chain, char **username)
|
||||||
{
|
{
|
||||||
int ret = 1, i, cert_count, fingerprint_match;
|
int ret = 1, i, cert_count, fingerprint_match;
|
||||||
char *digest_md5 = NULL, *digest_sha1 = NULL, *digest_sha224 = NULL;
|
char *digest_md5, *digest_sha1, *digest_sha224;
|
||||||
char *digest_sha256 = NULL, *digest_sha384 = NULL, *digest_sha512 = NULL;
|
char *digest_sha256, *digest_sha384, *digest_sha512;
|
||||||
void *cert;
|
void *cert;
|
||||||
|
|
||||||
/* first make sure the entry is valid */
|
/* first make sure the entry is valid */
|
||||||
|
@ -372,7 +372,6 @@ nc_server_tls_cert_to_name(struct nc_ctn *ctn, void *cert_chain, char **username
|
||||||
fingerprint_match = 1;
|
fingerprint_match = 1;
|
||||||
}
|
}
|
||||||
free(digest_md5);
|
free(digest_md5);
|
||||||
digest_md5 = NULL;
|
|
||||||
|
|
||||||
/* SHA-1 */
|
/* SHA-1 */
|
||||||
} else if (!strncmp(ctn->fingerprint, "02", 2)) {
|
} else if (!strncmp(ctn->fingerprint, "02", 2)) {
|
||||||
|
@ -388,7 +387,6 @@ nc_server_tls_cert_to_name(struct nc_ctn *ctn, void *cert_chain, char **username
|
||||||
fingerprint_match = 1;
|
fingerprint_match = 1;
|
||||||
}
|
}
|
||||||
free(digest_sha1);
|
free(digest_sha1);
|
||||||
digest_sha1 = NULL;
|
|
||||||
|
|
||||||
/* SHA-224 */
|
/* SHA-224 */
|
||||||
} else if (!strncmp(ctn->fingerprint, "03", 2)) {
|
} else if (!strncmp(ctn->fingerprint, "03", 2)) {
|
||||||
|
@ -404,7 +402,6 @@ nc_server_tls_cert_to_name(struct nc_ctn *ctn, void *cert_chain, char **username
|
||||||
fingerprint_match = 1;
|
fingerprint_match = 1;
|
||||||
}
|
}
|
||||||
free(digest_sha224);
|
free(digest_sha224);
|
||||||
digest_sha224 = NULL;
|
|
||||||
|
|
||||||
/* SHA-256 */
|
/* SHA-256 */
|
||||||
} else if (!strncmp(ctn->fingerprint, "04", 2)) {
|
} else if (!strncmp(ctn->fingerprint, "04", 2)) {
|
||||||
|
@ -420,7 +417,6 @@ nc_server_tls_cert_to_name(struct nc_ctn *ctn, void *cert_chain, char **username
|
||||||
fingerprint_match = 1;
|
fingerprint_match = 1;
|
||||||
}
|
}
|
||||||
free(digest_sha256);
|
free(digest_sha256);
|
||||||
digest_sha256 = NULL;
|
|
||||||
|
|
||||||
/* SHA-384 */
|
/* SHA-384 */
|
||||||
} else if (!strncmp(ctn->fingerprint, "05", 2)) {
|
} else if (!strncmp(ctn->fingerprint, "05", 2)) {
|
||||||
|
@ -436,7 +432,6 @@ nc_server_tls_cert_to_name(struct nc_ctn *ctn, void *cert_chain, char **username
|
||||||
fingerprint_match = 1;
|
fingerprint_match = 1;
|
||||||
}
|
}
|
||||||
free(digest_sha384);
|
free(digest_sha384);
|
||||||
digest_sha384 = NULL;
|
|
||||||
|
|
||||||
/* SHA-512 */
|
/* SHA-512 */
|
||||||
} else if (!strncmp(ctn->fingerprint, "06", 2)) {
|
} else if (!strncmp(ctn->fingerprint, "06", 2)) {
|
||||||
|
@ -452,7 +447,6 @@ nc_server_tls_cert_to_name(struct nc_ctn *ctn, void *cert_chain, char **username
|
||||||
fingerprint_match = 1;
|
fingerprint_match = 1;
|
||||||
}
|
}
|
||||||
free(digest_sha512);
|
free(digest_sha512);
|
||||||
digest_sha512 = NULL;
|
|
||||||
|
|
||||||
/* unknown */
|
/* unknown */
|
||||||
} else {
|
} else {
|
||||||
|
@ -658,7 +652,13 @@ nc_session_get_client_cert(const struct nc_session *session)
|
||||||
API void
|
API void
|
||||||
nc_server_tls_set_verify_clb(int (*verify_clb)(const struct nc_session *session))
|
nc_server_tls_set_verify_clb(int (*verify_clb)(const struct nc_session *session))
|
||||||
{
|
{
|
||||||
|
/* CONFIG LOCK */
|
||||||
|
pthread_rwlock_wrlock(&server_opts.config_lock);
|
||||||
|
|
||||||
server_opts.user_verify_clb = verify_clb;
|
server_opts.user_verify_clb = verify_clb;
|
||||||
|
|
||||||
|
/* CONFIG UNLOCK */
|
||||||
|
pthread_rwlock_unlock(&server_opts.config_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -69,6 +69,20 @@ struct nc_tls_verify_cb_data {
|
||||||
void *chain; /**< Certificate chain used to verify the client cert. */
|
void *chain; /**< Certificate chain used to verify the client cert. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the TLS backend.
|
||||||
|
*
|
||||||
|
* Does nothing for OpenSSL, required for MbedTLS version 3.6.0 and later.
|
||||||
|
*/
|
||||||
|
int nc_tls_backend_init_wrap(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destroys the TLS backend.
|
||||||
|
*
|
||||||
|
* Does nothing for OpenSSL, required for MbedTLS version 3.6.0 and later.
|
||||||
|
*/
|
||||||
|
void nc_tls_backend_destroy_wrap(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new TLS session from the given configuration.
|
* @brief Creates a new TLS session from the given configuration.
|
||||||
*
|
*
|
||||||
|
@ -267,8 +281,6 @@ void nc_tls_sans_destroy_wrap(void *sans);
|
||||||
*/
|
*/
|
||||||
int nc_tls_get_num_sans_wrap(void *sans);
|
int nc_tls_get_num_sans_wrap(void *sans);
|
||||||
|
|
||||||
#ifdef NC_ENABLED_SSH_TLS
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the SAN value and type in the context of CTN.
|
* @brief Get the SAN value and type in the context of CTN.
|
||||||
*
|
*
|
||||||
|
@ -280,8 +292,6 @@ int nc_tls_get_num_sans_wrap(void *sans);
|
||||||
*/
|
*/
|
||||||
int nc_tls_get_san_value_type_wrap(void *sans, int idx, char **san_value, NC_TLS_CTN_MAPTYPE *san_type);
|
int nc_tls_get_san_value_type_wrap(void *sans, int idx, char **san_value, NC_TLS_CTN_MAPTYPE *san_type);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the number of certificates in a certificate chain.
|
* @brief Get the number of certificates in a certificate chain.
|
||||||
*
|
*
|
||||||
|
|
|
@ -105,7 +105,7 @@ test_nc_rpc_act_generic(void **state)
|
||||||
|
|
||||||
/* function to check if values of getconfig rpc are set correctly */
|
/* function to check if values of getconfig rpc are set correctly */
|
||||||
void
|
void
|
||||||
check_getconfig(struct nc_rpc *rpc, enum NC_DATASTORE_TYPE source, char *filter, NC_WD_MODE wd_mode)
|
check_getconfig(struct nc_rpc *rpc, NC_DATASTORE source, char *filter, NC_WD_MODE wd_mode)
|
||||||
{
|
{
|
||||||
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_GETCONFIG);
|
assert_int_equal(nc_rpc_get_type(rpc), NC_RPC_GETCONFIG);
|
||||||
struct nc_rpc_getconfig *getconfig_rpc = (struct nc_rpc_getconfig *)rpc;
|
struct nc_rpc_getconfig *getconfig_rpc = (struct nc_rpc_getconfig *)rpc;
|
||||||
|
|
|
@ -240,6 +240,7 @@ test_send_recv_error(void)
|
||||||
NC_MSG_TYPE msgtype;
|
NC_MSG_TYPE msgtype;
|
||||||
struct nc_rpc *rpc;
|
struct nc_rpc *rpc;
|
||||||
struct lyd_node *envp, *op, *node;
|
struct lyd_node *envp, *op, *node;
|
||||||
|
const struct lysc_node *schema;
|
||||||
struct nc_pollsession *ps;
|
struct nc_pollsession *ps;
|
||||||
|
|
||||||
/* client RPC */
|
/* client RPC */
|
||||||
|
@ -266,9 +267,10 @@ test_send_recv_error(void)
|
||||||
|
|
||||||
nc_rpc_free(rpc);
|
nc_rpc_free(rpc);
|
||||||
assert_string_equal(LYD_NAME(lyd_child(envp)), "rpc-error");
|
assert_string_equal(LYD_NAME(lyd_child(envp)), "rpc-error");
|
||||||
lyd_find_sibling_opaq_next(lyd_child(lyd_child(envp)), "error-tag", &node);
|
schema = lys_find_path(LYD_CTX(envp), NULL, "/ietf-netconf:rpc-error/error-tag", 0);
|
||||||
|
lyd_find_sibling_val(lyd_child(lyd_child(envp)), schema, NULL, 0, &node);
|
||||||
assert_non_null(node);
|
assert_non_null(node);
|
||||||
assert_string_equal(((struct lyd_node_opaq *)node)->value, "operation-not-supported");
|
assert_string_equal(lyd_get_value(node), "operation-not-supported");
|
||||||
lyd_free_tree(envp);
|
lyd_free_tree(envp);
|
||||||
assert_null(op);
|
assert_null(op);
|
||||||
}
|
}
|
||||||
|
@ -508,6 +510,7 @@ test_send_recv_malformed_10(void **state)
|
||||||
struct nc_pollsession *ps;
|
struct nc_pollsession *ps;
|
||||||
struct nc_rpc *rpc;
|
struct nc_rpc *rpc;
|
||||||
struct lyd_node *envp, *op, *node;
|
struct lyd_node *envp, *op, *node;
|
||||||
|
const struct lysc_node *schema;
|
||||||
NC_MSG_TYPE msgtype;
|
NC_MSG_TYPE msgtype;
|
||||||
const char *msg;
|
const char *msg;
|
||||||
|
|
||||||
|
@ -543,9 +546,10 @@ test_send_recv_malformed_10(void **state)
|
||||||
|
|
||||||
nc_rpc_free(rpc);
|
nc_rpc_free(rpc);
|
||||||
assert_string_equal(LYD_NAME(lyd_child(envp)), "rpc-error");
|
assert_string_equal(LYD_NAME(lyd_child(envp)), "rpc-error");
|
||||||
lyd_find_sibling_opaq_next(lyd_child(lyd_child(envp)), "error-tag", &node);
|
schema = lys_find_path(LYD_CTX(envp), NULL, "/ietf-netconf:rpc-error/error-tag", 0);
|
||||||
|
lyd_find_sibling_val(lyd_child(lyd_child(envp)), schema, NULL, 0, &node);
|
||||||
assert_non_null(node);
|
assert_non_null(node);
|
||||||
assert_string_equal(((struct lyd_node_opaq *)node)->value, "missing-attribute");
|
assert_string_equal(lyd_get_value(node), "missing-attribute");
|
||||||
lyd_free_tree(envp);
|
lyd_free_tree(envp);
|
||||||
assert_null(op);
|
assert_null(op);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ setup_write(void **state)
|
||||||
/* ietf-netconf */
|
/* ietf-netconf */
|
||||||
fd = open(TESTS_DIR "/data/modules/ietf-netconf.yin", O_RDONLY);
|
fd = open(TESTS_DIR "/data/modules/ietf-netconf.yin", O_RDONLY);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
|
free(w->session);
|
||||||
free(w);
|
free(w);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,8 +46,19 @@ typedef struct arg {
|
||||||
struct nc_server_reply *
|
struct nc_server_reply *
|
||||||
rpc_clb(struct lyd_node *rpc, struct nc_session *session)
|
rpc_clb(struct lyd_node *rpc, struct nc_session *session)
|
||||||
{
|
{
|
||||||
(void)rpc; (void)session;
|
struct lyd_node *e;
|
||||||
return nc_server_reply_ok();
|
|
||||||
|
(void)session;
|
||||||
|
|
||||||
|
if (!strcmp(LYD_NAME(rpc), "get") || !strcmp(LYD_NAME(rpc), "delete-config")) {
|
||||||
|
return nc_server_reply_ok();
|
||||||
|
} else if (!strcmp(LYD_NAME(rpc), "commit")) {
|
||||||
|
e = nc_err(LYD_CTX(rpc), NC_ERR_RES_DENIED, NC_ERR_TYPE_APP);
|
||||||
|
nc_err_set_path(e, "/module-a:top/name");
|
||||||
|
return nc_server_reply_err(e);
|
||||||
|
} else {
|
||||||
|
nc_assert(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
|
@ -92,10 +103,14 @@ server_thread(void *arg)
|
||||||
|
|
||||||
nc_server_notif_send(sess, notif, 1000);
|
nc_server_notif_send(sess, notif, 1000);
|
||||||
|
|
||||||
|
/* commit in test */
|
||||||
|
poll = nc_ps_poll(ps, 1000, &sess);
|
||||||
|
nc_assert(poll == (NC_PSPOLL_RPC | NC_PSPOLL_REPLY_ERROR));
|
||||||
|
|
||||||
nc_ps_clear(ps, 1, NULL);
|
nc_ps_clear(ps, 1, NULL);
|
||||||
nc_ps_free(ps);
|
nc_ps_free(ps);
|
||||||
|
|
||||||
/* Waiting for end of test */
|
/* waiting for end of test */
|
||||||
pthread_barrier_wait(&barrier);
|
pthread_barrier_wait(&barrier);
|
||||||
|
|
||||||
nc_server_notif_free(notif);
|
nc_server_notif_free(notif);
|
||||||
|
@ -110,7 +125,7 @@ notif_thread(void *arg)
|
||||||
struct lyd_node *op;
|
struct lyd_node *op;
|
||||||
NC_MSG_TYPE msgtype;
|
NC_MSG_TYPE msgtype;
|
||||||
|
|
||||||
/* Sync threads for receiving message to increase chance of datarace */
|
/* sync threads for receiving message to increase chance of datarace */
|
||||||
pthread_barrier_wait(&barrier_msg);
|
pthread_barrier_wait(&barrier_msg);
|
||||||
do {
|
do {
|
||||||
msgtype = nc_recv_notif(sess, 1000, &envp, &op);
|
msgtype = nc_recv_notif(sess, 1000, &envp, &op);
|
||||||
|
@ -131,44 +146,47 @@ main(void)
|
||||||
struct nc_rpc *rpc;
|
struct nc_rpc *rpc;
|
||||||
uint64_t msgid;
|
uint64_t msgid;
|
||||||
NC_MSG_TYPE msgtype;
|
NC_MSG_TYPE msgtype;
|
||||||
const char *features[] = {"startup", NULL};
|
const char *features[] = {"startup", "candidate", NULL};
|
||||||
arg_t thread_arg;
|
arg_t thread_arg;
|
||||||
pthread_t t[2];
|
pthread_t t[2];
|
||||||
|
char *str;
|
||||||
|
|
||||||
pthread_barrier_init(&barrier, NULL, 2);
|
pthread_barrier_init(&barrier, NULL, 2);
|
||||||
pthread_barrier_init(&barrier_msg, NULL, 2);
|
pthread_barrier_init(&barrier_msg, NULL, 2);
|
||||||
|
|
||||||
/* Create a two pipes */
|
/* create a two pipes */
|
||||||
nc_assert(pipe(pipes) != -1);
|
nc_assert(pipe(pipes) != -1);
|
||||||
nc_assert(pipe(pipes + 2) != -1);
|
nc_assert(pipe(pipes + 2) != -1);
|
||||||
thread_arg.in = pipes[0];
|
thread_arg.in = pipes[0];
|
||||||
thread_arg.out = pipes[3];
|
thread_arg.out = pipes[3];
|
||||||
|
|
||||||
/* Create both contexts */
|
/* create both contexts */
|
||||||
nc_assert(ly_ctx_new(TESTS_DIR "/data/modules", 0, &server_ctx) == LY_SUCCESS);
|
nc_assert(ly_ctx_new(TESTS_DIR "/data/modules", 0, &server_ctx) == LY_SUCCESS);
|
||||||
nc_assert(ly_ctx_load_module(server_ctx, "ietf-netconf", NULL, features));
|
nc_assert(ly_ctx_load_module(server_ctx, "ietf-netconf", NULL, features));
|
||||||
nc_assert(ly_ctx_load_module(server_ctx, "notif1", NULL, NULL));
|
nc_assert(ly_ctx_load_module(server_ctx, "notif1", NULL, NULL));
|
||||||
|
nc_assert(ly_ctx_load_module(server_ctx, "module-a", NULL, NULL));
|
||||||
thread_arg.ctx = server_ctx;
|
thread_arg.ctx = server_ctx;
|
||||||
nc_set_global_rpc_clb(rpc_clb);
|
nc_set_global_rpc_clb(rpc_clb);
|
||||||
|
|
||||||
nc_assert(ly_ctx_new(TESTS_DIR "/data/modules", 0, &client_ctx) == LY_SUCCESS);
|
nc_assert(ly_ctx_new(TESTS_DIR "/data/modules", 0, &client_ctx) == LY_SUCCESS);
|
||||||
nc_assert(ly_ctx_load_module(client_ctx, "ietf-netconf", NULL, features));
|
nc_assert(ly_ctx_load_module(client_ctx, "ietf-netconf", NULL, features));
|
||||||
nc_assert(ly_ctx_load_module(client_ctx, "notif1", NULL, NULL));
|
nc_assert(ly_ctx_load_module(client_ctx, "notif1", NULL, NULL));
|
||||||
|
nc_assert(ly_ctx_load_module(client_ctx, "module-a", NULL, NULL));
|
||||||
|
|
||||||
/* Start server thread */
|
/* start server thread */
|
||||||
pthread_create(&t[0], NULL, server_thread, &thread_arg);
|
pthread_create(&t[0], NULL, server_thread, &thread_arg);
|
||||||
nc_client_init();
|
nc_client_init();
|
||||||
|
|
||||||
/* Listen for notifications */
|
/* listen for notifications */
|
||||||
sess = nc_connect_inout(pipes[2], pipes[1], client_ctx);
|
sess = nc_connect_inout(pipes[2], pipes[1], client_ctx);
|
||||||
nc_assert(sess);
|
nc_assert(sess);
|
||||||
pthread_create(&t[1], NULL, notif_thread, sess);
|
pthread_create(&t[1], NULL, notif_thread, sess);
|
||||||
|
|
||||||
/* Send rpc */
|
/* send delete-config rpc */
|
||||||
rpc = nc_rpc_delete(NC_DATASTORE_STARTUP, NULL, NC_PARAMTYPE_CONST);
|
rpc = nc_rpc_delete(NC_DATASTORE_STARTUP, NULL, NC_PARAMTYPE_CONST);
|
||||||
nc_assert(nc_send_rpc(sess, rpc, 1000, &msgid) == NC_MSG_RPC);
|
nc_assert(nc_send_rpc(sess, rpc, 1000, &msgid) == NC_MSG_RPC);
|
||||||
|
|
||||||
/* Sync threads for receiving message to increase chance of datarace */
|
/* sync threads for receiving message to increase chance of datarace */
|
||||||
pthread_barrier_wait(&barrier_msg);
|
pthread_barrier_wait(&barrier_msg);
|
||||||
do {
|
do {
|
||||||
msgtype = nc_recv_reply(sess, rpc, msgid, 1000, &envp, &op);
|
msgtype = nc_recv_reply(sess, rpc, msgid, 1000, &envp, &op);
|
||||||
|
@ -177,12 +195,33 @@ main(void)
|
||||||
nc_rpc_free(rpc);
|
nc_rpc_free(rpc);
|
||||||
lyd_free_tree(envp);
|
lyd_free_tree(envp);
|
||||||
|
|
||||||
/* Waiting of end of test */
|
/* send commit rpc */
|
||||||
|
rpc = nc_rpc_commit(0, 0, NULL, NULL, NC_PARAMTYPE_CONST);
|
||||||
|
nc_assert(nc_send_rpc(sess, rpc, 1000, &msgid) == NC_MSG_RPC);
|
||||||
|
do {
|
||||||
|
msgtype = nc_recv_reply(sess, rpc, msgid, 1000, &envp, &op);
|
||||||
|
} while (msgtype == NC_MSG_NOTIF);
|
||||||
|
nc_assert(msgtype == NC_MSG_REPLY);
|
||||||
|
nc_rpc_free(rpc);
|
||||||
|
|
||||||
|
lyd_print_mem(&str, envp, LYD_XML, LYD_PRINT_SHRINK);
|
||||||
|
nc_assert(!strcmp(str,
|
||||||
|
"<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"3\"><rpc-error>"
|
||||||
|
"<error-type>application</error-type>"
|
||||||
|
"<error-tag>resource-denied</error-tag>"
|
||||||
|
"<error-severity>error</error-severity>"
|
||||||
|
"<error-path xmlns:a=\"urn:jmu:params:xml:ns:yang:module-a\">/a:top/a:name</error-path>"
|
||||||
|
"<error-message xml:lang=\"en\">Request could not be completed because of insufficient resources.</error-message>"
|
||||||
|
"</rpc-error></rpc-reply>"));
|
||||||
|
free(str);
|
||||||
|
lyd_free_tree(envp);
|
||||||
|
|
||||||
|
/* waiting of end of test */
|
||||||
pthread_barrier_wait(&barrier);
|
pthread_barrier_wait(&barrier);
|
||||||
pthread_join(t[0], NULL);
|
pthread_join(t[0], NULL);
|
||||||
pthread_join(t[1], NULL);
|
pthread_join(t[1], NULL);
|
||||||
|
|
||||||
/* Cleanup */
|
/* cleanup */
|
||||||
nc_session_free(sess, NULL);
|
nc_session_free(sess, NULL);
|
||||||
ly_ctx_destroy(server_ctx);
|
ly_ctx_destroy(server_ctx);
|
||||||
ly_ctx_destroy(client_ctx);
|
ly_ctx_destroy(client_ctx);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue