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
|
||||
# micro version is changed with a set of small changes or bugfixes anywhere in the project.
|
||||
set(LIBNETCONF2_MAJOR_VERSION 3)
|
||||
set(LIBNETCONF2_MINOR_VERSION 5)
|
||||
set(LIBNETCONF2_MICRO_VERSION 5)
|
||||
set(LIBNETCONF2_MINOR_VERSION 7)
|
||||
set(LIBNETCONF2_MICRO_VERSION 1)
|
||||
set(LIBNETCONF2_VERSION ${LIBNETCONF2_MAJOR_VERSION}.${LIBNETCONF2_MINOR_VERSION}.${LIBNETCONF2_MICRO_VERSION})
|
||||
|
||||
# Version of the library
|
||||
# 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.
|
||||
set(LIBNETCONF2_MAJOR_SOVERSION 4)
|
||||
set(LIBNETCONF2_MINOR_SOVERSION 4)
|
||||
set(LIBNETCONF2_MICRO_SOVERSION 5)
|
||||
set(LIBNETCONF2_MINOR_SOVERSION 6)
|
||||
set(LIBNETCONF2_MICRO_SOVERSION 1)
|
||||
set(LIBNETCONF2_SOVERSION_FULL ${LIBNETCONF2_MAJOR_SOVERSION}.${LIBNETCONF2_MINOR_SOVERSION}.${LIBNETCONF2_MICRO_SOVERSION})
|
||||
set(LIBNETCONF2_SOVERSION ${LIBNETCONF2_MAJOR_SOVERSION})
|
||||
|
||||
# Version of libyang library that this project depends on
|
||||
set(LIBYANG_DEP_VERSION 2.0.0)
|
||||
set(LIBYANG_DEP_SOVERSION 3.0.0)
|
||||
set(LIBYANG_DEP_VERSION 3.12.0)
|
||||
set(LIBYANG_DEP_SOVERSION 3.9.0)
|
||||
set(LIBYANG_DEP_SOVERSION_MAJOR 3)
|
||||
|
||||
# global C flags
|
||||
|
@ -388,7 +388,7 @@ endif()
|
|||
|
||||
# generate API/ABI report
|
||||
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()
|
||||
|
||||
# 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");
|
||||
}
|
||||
|
||||
static enum NC_DATASTORE_TYPE
|
||||
static NC_DATASTORE
|
||||
string2datastore(const char *str)
|
||||
{
|
||||
if (!str) {
|
||||
|
@ -68,7 +68,7 @@ string2datastore(const char *str)
|
|||
static int
|
||||
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;
|
||||
uint64_t msg_id = 0;
|
||||
struct lyd_node *envp = NULL, *op = NULL;
|
||||
|
|
|
@ -31,6 +31,10 @@ module libnetconf2-netconf-server {
|
|||
prefix tlss;
|
||||
}
|
||||
|
||||
revision "2025-01-23" {
|
||||
description "Added a list of YANG modules skipped in the server <hello> message.";
|
||||
}
|
||||
|
||||
revision "2024-07-09" {
|
||||
description "Second revision.";
|
||||
}
|
||||
|
@ -428,11 +432,11 @@ module libnetconf2-netconf-server {
|
|||
if-feature "ct:certificate-expiration-notification";
|
||||
|
||||
description
|
||||
"Container for the certificate expiration notification intervals.
|
||||
Its child nodes describe the ability to set the time intervals for the certificate
|
||||
expiration notifications. These intervals are given in the form of an anchor and a period.
|
||||
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.
|
||||
Additionally, notifications are generated on the day of expiration and every day thereafter.
|
||||
"Container for the certificate expiration notification intervals. Its child nodes describe the ability to set
|
||||
the time intervals for the certificate expiration notifications. These intervals are given in the form of an
|
||||
anchor and a period. 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. Additionally, notifications are generated on the day of expiration
|
||||
and every day thereafter.
|
||||
|
||||
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 "session.h"
|
||||
#include "session_p.h"
|
||||
|
||||
#ifdef NC_ENABLED_SSH_TLS
|
||||
|
||||
#include "session_wrapper.h"
|
||||
|
||||
#endif /* NC_ENABLED_SSH_TLS */
|
||||
|
||||
const char *nc_msgtype2str[] = {
|
||||
"error",
|
||||
"would block",
|
||||
|
@ -938,6 +943,7 @@ nc_write_msg_io(struct nc_session *session, int io_timeout, int type, ...)
|
|||
|
||||
switch (reply->type) {
|
||||
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)) {
|
||||
lyd_free_tree(reply_envp);
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ nc_libssh_thread_verbosity(int level)
|
|||
|
||||
#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)
|
||||
{
|
||||
va_list args2;
|
||||
|
@ -140,6 +140,7 @@ nc_log_vprintf(const struct nc_session *session, NC_VERB_LEVEL level, const char
|
|||
|
||||
cleanup:
|
||||
free(msg);
|
||||
va_end(args2);
|
||||
}
|
||||
|
||||
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, ...);
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
/**
|
||||
* @file messages_p.h
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief libnetconf2's private functions and structures of NETCONF messages.
|
||||
*
|
||||
* @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").
|
||||
* 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 {
|
||||
NC_RPL type;
|
||||
struct lyd_node *data;
|
||||
struct lyd_node *data; /**< always points to the operation, for both RPCs and actions */
|
||||
int free;
|
||||
NC_WD_MODE wd;
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* @brief libnetconf2 - server NETCONF messages functions
|
||||
*
|
||||
* @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").
|
||||
* 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;
|
||||
struct lyd_node *err = NULL;
|
||||
const struct lys_module *nc_mod;
|
||||
NC_ERR_TYPE type;
|
||||
const char *arg1, *arg2;
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -337,17 +344,17 @@ nc_err(const struct ly_ctx *ctx, NC_ERR tag, ...)
|
|||
ERRARG(NULL, "tag");
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -474,13 +481,17 @@ fail:
|
|||
API NC_ERR_TYPE
|
||||
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);
|
||||
|
||||
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) {
|
||||
return nc_err_str2type(((struct lyd_node_opaq *)match)->value);
|
||||
return nc_err_str2type(lyd_get_value(match));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -489,13 +500,17 @@ nc_err_get_type(const struct lyd_node *err)
|
|||
API NC_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);
|
||||
|
||||
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) {
|
||||
return nc_err_str2tag(((struct lyd_node_opaq *)match)->value);
|
||||
return nc_err_str2tag(lyd_get_value(match));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -504,17 +519,25 @@ nc_err_get_tag(const struct lyd_node *err)
|
|||
API int
|
||||
nc_err_set_app_tag(struct lyd_node *err, const char *error_app_tag)
|
||||
{
|
||||
const struct lysc_node *schema;
|
||||
struct lyd_node *match;
|
||||
|
||||
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 */
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -524,13 +547,17 @@ nc_err_set_app_tag(struct lyd_node *err, const char *error_app_tag)
|
|||
API const char *
|
||||
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);
|
||||
|
||||
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) {
|
||||
return ((struct lyd_node_opaq *)match)->value;
|
||||
return lyd_get_value(match);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -539,17 +566,25 @@ nc_err_get_app_tag(const struct lyd_node *err)
|
|||
API int
|
||||
nc_err_set_path(struct lyd_node *err, const char *error_path)
|
||||
{
|
||||
const struct lysc_node *schema;
|
||||
struct lyd_node *match;
|
||||
|
||||
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 */
|
||||
lyd_find_sibling_opaq_next(lyd_child(err), "error-path", &match);
|
||||
lyd_find_sibling_val(lyd_child(err), schema, NULL, 0, &match);
|
||||
if (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;
|
||||
}
|
||||
|
||||
|
@ -559,13 +594,17 @@ nc_err_set_path(struct lyd_node *err, const char *error_path)
|
|||
API const char *
|
||||
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);
|
||||
|
||||
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) {
|
||||
return ((struct lyd_node_opaq *)match)->value;
|
||||
return lyd_get_value(match);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -574,21 +613,37 @@ nc_err_get_path(const struct lyd_node *err)
|
|||
API int
|
||||
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;
|
||||
|
||||
NC_CHECK_ARG_RET(NULL, err, error_message, -1);
|
||||
|
||||
/* remove previous node */
|
||||
lyd_find_sibling_opaq_next(lyd_child(err), "error-message", &match);
|
||||
if (match) {
|
||||
/* Change the value of error-message and keep order of elements to comply with appendix-B in RFC 6241. */
|
||||
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;
|
||||
lyd_free_tree(match);
|
||||
}
|
||||
|
||||
/* 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)) {
|
||||
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)) {
|
||||
lyd_free_tree(match);
|
||||
return -1;
|
||||
|
@ -733,6 +788,16 @@ nc_server_rpc_free(struct nc_server_rpc *rpc)
|
|||
free(rpc);
|
||||
}
|
||||
|
||||
API NC_RPL
|
||||
nc_server_reply_type(struct nc_server_reply *reply)
|
||||
{
|
||||
if (!reply) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return reply->type;
|
||||
}
|
||||
|
||||
API void
|
||||
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:
|
||||
data_rpl = (struct nc_server_reply_data *)reply;
|
||||
if (data_rpl->free) {
|
||||
lyd_free_siblings(data_rpl->data);
|
||||
lyd_free_all(data_rpl->data);
|
||||
}
|
||||
break;
|
||||
case NC_RPL_OK:
|
||||
|
@ -766,7 +831,7 @@ nc_server_reply_free(struct nc_server_reply *reply)
|
|||
API struct nc_server_notif *
|
||||
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;
|
||||
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) {
|
||||
ntf->eventtime = strdup(eventtime);
|
||||
NC_CHECK_ERRMEM_GOTO(!ntf->eventtime, , error);
|
||||
|
||||
if (lyd_dup_single(event, NULL, LYD_DUP_RECURSIVE, &ntf->ntf)) {
|
||||
free(ntf);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
|
||||
return ntf;
|
||||
|
||||
error:
|
||||
free(ntf->eventtime);
|
||||
free(ntf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
/**
|
||||
* @file netconf.h
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief libnetconf2's general public functions and structures definitions.
|
||||
*
|
||||
* @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").
|
||||
* 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.
|
||||
*/
|
||||
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_NONE = 0, /**< session still running */
|
||||
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.
|
||||
*/
|
||||
typedef enum NC_MSG_TYPE {
|
||||
typedef enum {
|
||||
NC_MSG_ERROR, /**< error return value */
|
||||
NC_MSG_WOULDBLOCK, /**< timeout return value */
|
||||
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
|
||||
*/
|
||||
typedef enum NC_DATASTORE_TYPE {
|
||||
typedef enum {
|
||||
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_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.
|
||||
*/
|
||||
typedef enum NC_WITHDEFAULTS_MODE {
|
||||
typedef enum {
|
||||
NC_WD_UNKNOWN = 0, /**< invalid mode */
|
||||
NC_WD_ALL, /**< report-all 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.
|
||||
*/
|
||||
typedef enum NC_REPLY {
|
||||
typedef enum {
|
||||
NC_RPL_OK, /**< OK rpc-reply */
|
||||
NC_RPL_DATA, /**< DATA rpc-reply */
|
||||
NC_RPL_ERROR, /**< ERROR rpc-reply */
|
||||
|
@ -118,7 +119,7 @@ typedef enum NC_REPLY {
|
|||
/**
|
||||
* @brief Enumeration of function parameter treatments.
|
||||
*/
|
||||
typedef enum NC_PARAMTYPE {
|
||||
typedef enum {
|
||||
NC_PARAMTYPE_CONST, /**< use the parameter directly, do not free */
|
||||
NC_PARAMTYPE_FREE, /**< use the parameter directly, 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 */
|
||||
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)) {
|
||||
ret = 1;
|
||||
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"));
|
||||
|
||||
/* 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);
|
||||
assert(n);
|
||||
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
|
||||
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));
|
||||
|
||||
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
|
||||
/* delete the intervals */
|
||||
|
@ -4155,6 +4170,45 @@ cleanup:
|
|||
|
||||
#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
|
||||
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);
|
||||
}
|
||||
#endif /* NC_ENABLED_SSH_TLS */
|
||||
else if (!strcmp(name, "ignored-hello-module")) {
|
||||
ret = nc_server_config_ignored_module(node, op);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
ERR(NULL, "Configuring node \"%s\" failed.", LYD_NAME(node));
|
||||
|
|
|
@ -29,8 +29,13 @@
|
|||
#include "log_p.h"
|
||||
#include "session.h"
|
||||
#include "session_p.h"
|
||||
|
||||
#ifdef NC_ENABLED_SSH_TLS
|
||||
|
||||
#include "session_wrapper.h"
|
||||
|
||||
#endif /* NC_ENABLED_SSH_TLS */
|
||||
|
||||
int
|
||||
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;
|
||||
char *hashed_pw = NULL;
|
||||
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);
|
||||
|
||||
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) {
|
||||
ERR(NULL, "Hashing password failed (%s).", strerror(errno));
|
||||
ret = 1;
|
||||
|
@ -515,6 +522,7 @@ _nc_server_config_add_ssh_user_password(const struct ly_ctx *ctx, const char *tr
|
|||
}
|
||||
|
||||
cleanup:
|
||||
free(cdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,9 +37,10 @@
|
|||
|
||||
#ifdef NC_ENABLED_SSH_TLS
|
||||
|
||||
#include "session_wrapper.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <libssh/libssh.h>
|
||||
#include "session_wrapper.h"
|
||||
|
||||
#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 timespec ts;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -948,7 +966,7 @@ nc_session_free(struct nc_session *session, void (*data_free)(void *))
|
|||
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 */
|
||||
while (nc_read_msg_poll_io(session, 0, &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");
|
||||
count = 2;
|
||||
|
||||
/* capabilities */
|
||||
|
||||
mod = ly_ctx_get_module_implemented(ctx, "ietf-netconf");
|
||||
if (mod) {
|
||||
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");
|
||||
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) {
|
||||
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 {
|
||||
strcpy(str, "urn:ietf:params:netconf:capability:with-defaults:1.0");
|
||||
switch (wd_basic_mode) {
|
||||
|
@ -1172,10 +1192,10 @@ nc_server_get_cpblts_version(const struct ly_ctx *ctx, LYS_VERSION version)
|
|||
break;
|
||||
default:
|
||||
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) {
|
||||
strcat(str, "&also-supported=");
|
||||
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 */
|
||||
u = 0;
|
||||
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 (!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.");
|
||||
goto error;
|
||||
goto unlock_error;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* HELLO UNLOCK */
|
||||
pthread_rwlock_unlock(&server_opts.hello_lock);
|
||||
|
||||
/* ending NULL capability */
|
||||
add_cpblt(NULL, &cpblts, &size, &count);
|
||||
|
||||
return cpblts;
|
||||
|
||||
unlock_error:
|
||||
/* HELLO UNLOCK */
|
||||
pthread_rwlock_unlock(&server_opts.hello_lock);
|
||||
|
||||
error:
|
||||
free(cpblts);
|
||||
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;
|
||||
i = getaddrinfo(dst_addr, dst_port_str, &hints, &res_list);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2006,6 +2006,10 @@ nc_client_init(void)
|
|||
}
|
||||
|
||||
#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()) {
|
||||
ERR(NULL, "%s: failed to init libssh.", __func__);
|
||||
return -1;
|
||||
|
@ -2024,6 +2028,7 @@ nc_client_destroy(void)
|
|||
nc_client_ch_del_bind(NULL, 0, 0);
|
||||
nc_client_ssh_destroy_opts();
|
||||
nc_client_tls_destroy_opts();
|
||||
nc_tls_backend_destroy_wrap();
|
||||
ssh_finalize();
|
||||
#endif /* NC_ENABLED_SSH_TLS */
|
||||
}
|
||||
|
|
|
@ -52,29 +52,79 @@
|
|||
#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] err MbedTLS error code.
|
||||
* @return Error string.
|
||||
* @param[in] session NETCONF session.
|
||||
* @param[in] mbedtls_err_code MbedTLS error code.
|
||||
* @param[in] orig_err_msg_fmt Original error message format string.
|
||||
* @param[in] ... Additional arguments for the original error message.
|
||||
*/
|
||||
static const char *
|
||||
nc_get_mbedtls_str_err(int err)
|
||||
static void
|
||||
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);
|
||||
if (err_str) {
|
||||
return err_str;
|
||||
va_start(args, orig_err_msg_fmt);
|
||||
|
||||
/* 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 (err_str) {
|
||||
return err_str;
|
||||
if (high_err_str && low_err_str) {
|
||||
/* for a colon and 2 spaces */
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -194,6 +244,27 @@ nc_tls_get_verify_err_str(int err)
|
|||
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 *
|
||||
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);
|
||||
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);
|
||||
free(session);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -755,7 +826,7 @@ nc_server_tls_md5_wrap(void *cert, unsigned char *buf)
|
|||
|
||||
rc = mbedtls_md5(c->raw.p, c->raw.len, buf);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -770,7 +841,7 @@ nc_server_tls_sha1_wrap(void *cert, unsigned char *buf)
|
|||
|
||||
rc = mbedtls_sha1(c->raw.p, c->raw.len, buf);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
nc_tls_rng_destroy(ctr_drbg, entropy);
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1027,12 +1098,12 @@ nc_client_tls_load_trusted_certs_wrap(void *cert_store, const char *file_path, c
|
|||
int rc;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1046,7 +1117,7 @@ nc_client_tls_set_hostname_wrap(void *tls_session, const char *hostname)
|
|||
|
||||
rc = mbedtls_ssl_set_hostname(tls_session, hostname);
|
||||
if (rc) {
|
||||
ERR(NULL, "Setting hostname failed (%s).", nc_get_mbedtls_str_err(rc));
|
||||
nc_mbedtls_strerr(NULL, rc, "Setting hostname failed");
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1111,25 +1182,17 @@ nc_tls_verify_error_string_wrap(uint32_t err_code)
|
|||
void
|
||||
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 (err) {
|
||||
ERR(NULL, "TLS connection to \"%s\" failed (%s).", peername, err);
|
||||
if (peername) {
|
||||
nc_mbedtls_strerr(NULL, connect_ret, "TLS connect to host \"%s\" failed", peername);
|
||||
} else {
|
||||
ERR(NULL, "TLS connection to \"%s\" failed.", peername);
|
||||
nc_mbedtls_strerr(NULL, connect_ret, "TLS connect to an unknown host failed");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nc_server_tls_print_accept_err_wrap(int accept_ret, void *UNUSED(tls_session))
|
||||
{
|
||||
const char *err = nc_get_mbedtls_str_err(accept_ret);
|
||||
|
||||
if (err) {
|
||||
ERR(NULL, "TLS accept failed (%s).", err);
|
||||
} else {
|
||||
ERR(NULL, "TLS accept failed.");
|
||||
}
|
||||
nc_mbedtls_strerr(NULL, accept_ret, "TLS accept failed");
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1158,7 +1221,7 @@ nc_base64_decode_wrap(const char *base64, unsigned char **bin)
|
|||
/* get the size of the decoded data */
|
||||
rc = mbedtls_base64_decode(NULL, 0, &size, (const unsigned char *)base64, strlen(base64));
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1168,7 +1231,7 @@ nc_base64_decode_wrap(const char *base64, unsigned char **bin)
|
|||
/* decode */
|
||||
rc = mbedtls_base64_decode(*bin, size, &size, (const unsigned char *)base64, strlen(base64));
|
||||
if (rc) {
|
||||
ERR(NULL, "Base64 decoding failed (%s).", nc_get_mbedtls_str_err(rc));
|
||||
nc_mbedtls_strerr(NULL, rc, "Base64 decoding failed");
|
||||
free(*bin);
|
||||
*bin = NULL;
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
if (rc) {
|
||||
ERR(NULL, "Base64 encoding failed (%s).", nc_get_mbedtls_str_err(rc));
|
||||
nc_mbedtls_strerr(NULL, rc, "Base64 encoding failed");
|
||||
free(*base64);
|
||||
*base64 = NULL;
|
||||
return -1;
|
||||
|
@ -1217,13 +1280,13 @@ nc_tls_read_wrap(struct nc_session *session, unsigned char *buf, size_t size)
|
|||
rc = 0;
|
||||
break;
|
||||
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->term_reason = NC_SESSION_TERM_DROPPED;
|
||||
rc = -1;
|
||||
break;
|
||||
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->term_reason = NC_SESSION_TERM_OTHER;
|
||||
rc = -1;
|
||||
|
@ -1248,11 +1311,11 @@ nc_tls_write_wrap(struct nc_session *session, const unsigned char *buf, size_t s
|
|||
rc = 0;
|
||||
break;
|
||||
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;
|
||||
break;
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
@ -1281,7 +1344,7 @@ nc_tls_close_notify_wrap(void *tls_session)
|
|||
while ((rc = mbedtls_ssl_close_notify(tls_session))) {
|
||||
if ((rc != MBEDTLS_ERR_SSL_WANT_READ) && (rc != MBEDTLS_ERR_SSL_WANT_WRITE)) {
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
@ -1300,7 +1363,7 @@ nc_tls_import_cert_file_wrap(const char *cert_path)
|
|||
|
||||
rc = mbedtls_x509_crt_parse_file(c, cert_path);
|
||||
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);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1324,7 +1387,7 @@ nc_tls_export_privkey_pem_wrap(void *pkey)
|
|||
NC_CHECK_ERRMEM_RET(!pem, NULL);
|
||||
}
|
||||
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);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1369,7 +1432,7 @@ nc_tls_export_pubkey_pem_wrap(void *pkey)
|
|||
NC_CHECK_ERRMEM_RET(!pem, NULL);
|
||||
}
|
||||
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);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1399,7 +1462,7 @@ nc_tls_get_rsa_pubkey_params_wrap(void *pkey, void **e, void **n)
|
|||
mbedtls_mpi_init(mod);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1468,7 +1531,7 @@ nc_tls_get_ec_pubkey_params_wrap(void *pkey, void **q, void **q_grp)
|
|||
/* get the group and public key */
|
||||
ret = mbedtls_ecp_export(mbedtls_pk_ec(*(mbedtls_pk_context *)pkey), grp, d, p);
|
||||
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;
|
||||
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);
|
||||
}
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
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).");
|
||||
goto cleanup;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
@ -1640,7 +1703,7 @@ nc_server_tls_parse_crl_dist_points(unsigned char **p, size_t len, char ***uris,
|
|||
end_general_names = *p + len;
|
||||
ret = mbedtls_asn1_get_tag(p, end_general_names, &name_len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
if (ret) {
|
||||
ERR(NULL, "Failed to parse GeneralName in CRL distribution points extension (%s).",
|
||||
nc_get_mbedtls_str_err(ret));
|
||||
nc_mbedtls_strerr(NULL, ret, "Failed to parse GeneralName in CRL distribution points extension");
|
||||
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) {
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1776,7 +1838,7 @@ nc_server_tls_get_crl_distpoint_uris_wrap(void *leaf_cert, void *cert_store, cha
|
|||
/* parse extnID */
|
||||
ret = mbedtls_asn1_get_tag(&p, end_ext, &ext_oid.len, MBEDTLS_ASN1_OID);
|
||||
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;
|
||||
}
|
||||
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 */
|
||||
ret = mbedtls_asn1_get_bool(&p, end_ext, &is_critical);
|
||||
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;
|
||||
}
|
||||
|
||||
/* parse extnValue */
|
||||
ret = mbedtls_asn1_get_tag(&p, end_ext, &len, MBEDTLS_ASN1_OCTET_STRING);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
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;
|
||||
}
|
||||
if (p + len != end_ext_octet) {
|
||||
/* 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;
|
||||
} else if (!len) {
|
||||
/* empty sequence, but size is 1..max */
|
||||
|
|
|
@ -44,6 +44,20 @@
|
|||
#include <openssl/x509.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 *
|
||||
nc_tls_session_new_wrap(void *tls_cfg)
|
||||
{
|
||||
|
|
|
@ -30,8 +30,13 @@
|
|||
#include "session_client.h"
|
||||
#include "session_server.h"
|
||||
#include "session_server_ch.h"
|
||||
|
||||
#ifdef NC_ENABLED_SSH_TLS
|
||||
|
||||
#include "session_wrapper.h"
|
||||
|
||||
#endif /* NC_ENABLED_SSH_TLS */
|
||||
|
||||
extern struct nc_server_opts server_opts;
|
||||
|
||||
/**
|
||||
|
@ -498,19 +503,27 @@ struct nc_ch_client_thread_arg {
|
|||
};
|
||||
|
||||
struct nc_server_opts {
|
||||
/* ACCESS unlocked */
|
||||
ATOMIC_T wd_basic_mode;
|
||||
ATOMIC_T wd_also_supported;
|
||||
uint32_t capabilities_count;
|
||||
/* ACCESS locked - hello lock - separate lock to not always hold config_lock */
|
||||
char **ignored_modules; /**< Names of YANG modules that are not reported in the server <hello> message. */
|
||||
uint16_t ignored_mod_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;
|
||||
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_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;
|
||||
|
||||
/* 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
|
||||
char *authkey_path_fmt; /**< Path to users' public keys that may contain tokens with special meaning. */
|
||||
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);
|
||||
#endif /* NC_ENABLED_SSH_TLS */
|
||||
|
||||
pthread_rwlock_t config_lock;
|
||||
|
||||
#ifdef NC_ENABLED_SSH_TLS
|
||||
struct nc_keystore keystore; /**< store for server's keys/certificates */
|
||||
struct nc_truststore truststore; /**< store for server client's keys/certificates */
|
||||
struct nc_keystore keystore; /**< Server's keys/certificates. */
|
||||
struct nc_truststore truststore; /**< Server client's keys/certificates. */
|
||||
#endif /* NC_ENABLED_SSH_TLS */
|
||||
|
||||
/* ACCESS locked */
|
||||
struct nc_bind *binds;
|
||||
pthread_mutex_t bind_lock; /**< To avoid concurrent calls of poll and accept on the bound sockets **/
|
||||
struct nc_endpt {
|
||||
|
@ -607,11 +619,12 @@ struct nc_server_opts {
|
|||
} ch_dispatch_data;
|
||||
#endif /* NC_ENABLED_SSH_TLS */
|
||||
|
||||
/* Atomic IDs */
|
||||
/* ACCESS unlocked */
|
||||
ATOMIC_T new_session_id;
|
||||
ATOMIC_T new_client_id;
|
||||
|
||||
#ifdef NC_ENABLED_SSH_TLS
|
||||
/* ACCESS locked */
|
||||
struct {
|
||||
pthread_t tid; /**< Thread ID of the certificate expiration 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. */
|
||||
} 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
|
||||
};
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
/**
|
||||
* @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
|
||||
* - io.c
|
||||
|
|
|
@ -44,14 +44,18 @@
|
|||
#include "session_p.h"
|
||||
#include "session_server.h"
|
||||
#include "session_server_ch.h"
|
||||
#include "session_wrapper.h"
|
||||
|
||||
#ifdef NC_ENABLED_SSH_TLS
|
||||
|
||||
#include "session_wrapper.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <libssh/libssh.h>
|
||||
#endif
|
||||
|
||||
#endif /* NC_ENABLED_SSH_TLS */
|
||||
|
||||
struct nc_server_opts server_opts = {
|
||||
.hello_lock = PTHREAD_RWLOCK_INITIALIZER,
|
||||
.config_lock = PTHREAD_RWLOCK_INITIALIZER,
|
||||
.ch_client_lock = PTHREAD_RWLOCK_INITIALIZER,
|
||||
.idle_timeout = 180, /**< default idle timeout (not in config for UNIX socket) */
|
||||
|
@ -818,41 +822,62 @@ nc_server_keylog_file_open(void)
|
|||
|
||||
#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
|
||||
nc_server_init(void)
|
||||
{
|
||||
pthread_rwlockattr_t *attr_p = NULL;
|
||||
int r;
|
||||
|
||||
ATOMIC_STORE_RELAXED(server_opts.new_session_id, 1);
|
||||
ATOMIC_STORE_RELAXED(server_opts.new_client_id, 1);
|
||||
|
||||
#ifdef HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP
|
||||
pthread_rwlockattr_t attr;
|
||||
|
||||
if ((r = pthread_rwlockattr_init(&attr))) {
|
||||
ERR(NULL, "%s: failed init attribute (%s).", __func__, strerror(r));
|
||||
if (nc_server_init_rwlock(&server_opts.config_lock)) {
|
||||
goto error;
|
||||
}
|
||||
attr_p = &attr;
|
||||
if ((r = pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP))) {
|
||||
ERR(NULL, "%s: failed set attribute (%s).", __func__, strerror(r));
|
||||
if (nc_server_init_rwlock(&server_opts.ch_client_lock)) {
|
||||
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
|
||||
if (curl_global_init(CURL_GLOBAL_SSL | CURL_GLOBAL_ACK_EINTR)) {
|
||||
|
@ -860,6 +885,11 @@ nc_server_init(void)
|
|||
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 */
|
||||
if (ssh_init()) {
|
||||
ERR(NULL, "%s: failed to init libssh.", __func__);
|
||||
|
@ -889,9 +919,6 @@ nc_server_init(void)
|
|||
return 0;
|
||||
|
||||
error:
|
||||
if (attr_p) {
|
||||
pthread_rwlockattr_destroy(attr_p);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -942,6 +969,7 @@ nc_server_destroy(void)
|
|||
nc_server_config_ks_keystore(NULL, NC_OP_DELETE);
|
||||
nc_server_config_ts_truststore(NULL, NC_OP_DELETE);
|
||||
curl_global_cleanup();
|
||||
nc_tls_backend_destroy_wrap();
|
||||
ssh_finalize();
|
||||
|
||||
/* close the TLS keylog file */
|
||||
|
@ -962,8 +990,15 @@ nc_server_set_capab_withdefaults(NC_WD_MODE basic_mode, int also_supported)
|
|||
return -1;
|
||||
}
|
||||
|
||||
ATOMIC_STORE_RELAXED(server_opts.wd_basic_mode, basic_mode);
|
||||
ATOMIC_STORE_RELAXED(server_opts.wd_also_supported, also_supported);
|
||||
/* HELLO LOCK */
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -975,12 +1010,18 @@ nc_server_get_capab_withdefaults(NC_WD_MODE *basic_mode, int *also_supported)
|
|||
return;
|
||||
}
|
||||
|
||||
/* HELLO LOCK */
|
||||
pthread_rwlock_wrlock(&server_opts.hello_lock);
|
||||
|
||||
if (basic_mode) {
|
||||
*basic_mode = ATOMIC_LOAD_RELAXED(server_opts.wd_basic_mode);
|
||||
*basic_mode = server_opts.wd_basic_mode;
|
||||
}
|
||||
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
|
||||
|
@ -993,6 +1034,9 @@ nc_server_set_capability(const char *value)
|
|||
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);
|
||||
NC_CHECK_ERRMEM_RET(!mem, EXIT_FAILURE);
|
||||
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_count++;
|
||||
|
||||
/* HELLO UNLOCK */
|
||||
pthread_rwlock_unlock(&server_opts.hello_lock);
|
||||
|
||||
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,
|
||||
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_data = user_data;
|
||||
server_opts.content_id_data_free = free_user_data;
|
||||
|
||||
/* HELLO UNLOCK */
|
||||
pthread_rwlock_unlock(&server_opts.hello_lock);
|
||||
}
|
||||
|
||||
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;
|
||||
int sock, ret;
|
||||
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,
|
||||
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 */
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
|
@ -645,13 +646,23 @@ nc_server_ssh_compare_password(const char *stored_pw, const char *received_pw)
|
|||
return strcmp(stored_pw + 3, received_pw);
|
||||
}
|
||||
|
||||
received_pw_hash = crypt_r(received_pw, stored_pw, &cdata);
|
||||
if (!received_pw_hash) {
|
||||
ERR(NULL, "Hashing the password failed (%s).", strerror(errno));
|
||||
cdata = (struct crypt_data *) calloc(sizeof(struct crypt_data), 1);
|
||||
if (cdata == NULL) {
|
||||
ERR(NULL, "Allocation of crypt_data struct failed.");
|
||||
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
|
||||
|
@ -1946,17 +1957,29 @@ nc_accept_ssh_session(struct nc_session *session, struct nc_server_ssh_opts *opt
|
|||
rc = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
if (opts->encryption_algs && ssh_bind_options_set(sbind, SSH_BIND_OPTIONS_CIPHERS_S_C, opts->encryption_algs)) {
|
||||
rc = -1;
|
||||
goto cleanup;
|
||||
if (opts->encryption_algs) {
|
||||
if (ssh_bind_options_set(sbind, SSH_BIND_OPTIONS_CIPHERS_S_C, opts->encryption_algs)) {
|
||||
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)) {
|
||||
rc = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
if (opts->mac_algs && ssh_bind_options_set(sbind, SSH_BIND_OPTIONS_HMAC_S_C, opts->mac_algs)) {
|
||||
rc = -1;
|
||||
goto cleanup;
|
||||
if (opts->mac_algs) {
|
||||
if (ssh_bind_options_set(sbind, SSH_BIND_OPTIONS_HMAC_S_C, opts->mac_algs)) {
|
||||
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 */
|
||||
|
|
|
@ -331,8 +331,8 @@ static int
|
|||
nc_server_tls_cert_to_name(struct nc_ctn *ctn, void *cert_chain, char **username)
|
||||
{
|
||||
int ret = 1, i, cert_count, fingerprint_match;
|
||||
char *digest_md5 = NULL, *digest_sha1 = NULL, *digest_sha224 = NULL;
|
||||
char *digest_sha256 = NULL, *digest_sha384 = NULL, *digest_sha512 = NULL;
|
||||
char *digest_md5, *digest_sha1, *digest_sha224;
|
||||
char *digest_sha256, *digest_sha384, *digest_sha512;
|
||||
void *cert;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
free(digest_md5);
|
||||
digest_md5 = NULL;
|
||||
|
||||
/* SHA-1 */
|
||||
} 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;
|
||||
}
|
||||
free(digest_sha1);
|
||||
digest_sha1 = NULL;
|
||||
|
||||
/* SHA-224 */
|
||||
} 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;
|
||||
}
|
||||
free(digest_sha224);
|
||||
digest_sha224 = NULL;
|
||||
|
||||
/* SHA-256 */
|
||||
} 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;
|
||||
}
|
||||
free(digest_sha256);
|
||||
digest_sha256 = NULL;
|
||||
|
||||
/* SHA-384 */
|
||||
} 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;
|
||||
}
|
||||
free(digest_sha384);
|
||||
digest_sha384 = NULL;
|
||||
|
||||
/* SHA-512 */
|
||||
} 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;
|
||||
}
|
||||
free(digest_sha512);
|
||||
digest_sha512 = NULL;
|
||||
|
||||
/* unknown */
|
||||
} else {
|
||||
|
@ -658,7 +652,13 @@ nc_session_get_client_cert(const struct nc_session *session)
|
|||
API void
|
||||
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;
|
||||
|
||||
/* CONFIG UNLOCK */
|
||||
pthread_rwlock_unlock(&server_opts.config_lock);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -69,6 +69,20 @@ struct nc_tls_verify_cb_data {
|
|||
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.
|
||||
*
|
||||
|
@ -267,8 +281,6 @@ void nc_tls_sans_destroy_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.
|
||||
*
|
||||
|
@ -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);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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 */
|
||||
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);
|
||||
struct nc_rpc_getconfig *getconfig_rpc = (struct nc_rpc_getconfig *)rpc;
|
||||
|
|
|
@ -240,6 +240,7 @@ test_send_recv_error(void)
|
|||
NC_MSG_TYPE msgtype;
|
||||
struct nc_rpc *rpc;
|
||||
struct lyd_node *envp, *op, *node;
|
||||
const struct lysc_node *schema;
|
||||
struct nc_pollsession *ps;
|
||||
|
||||
/* client RPC */
|
||||
|
@ -266,9 +267,10 @@ test_send_recv_error(void)
|
|||
|
||||
nc_rpc_free(rpc);
|
||||
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_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);
|
||||
assert_null(op);
|
||||
}
|
||||
|
@ -508,6 +510,7 @@ test_send_recv_malformed_10(void **state)
|
|||
struct nc_pollsession *ps;
|
||||
struct nc_rpc *rpc;
|
||||
struct lyd_node *envp, *op, *node;
|
||||
const struct lysc_node *schema;
|
||||
NC_MSG_TYPE msgtype;
|
||||
const char *msg;
|
||||
|
||||
|
@ -543,9 +546,10 @@ test_send_recv_malformed_10(void **state)
|
|||
|
||||
nc_rpc_free(rpc);
|
||||
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_string_equal(((struct lyd_node_opaq *)node)->value, "missing-attribute");
|
||||
assert_string_equal(lyd_get_value(node), "missing-attribute");
|
||||
lyd_free_tree(envp);
|
||||
assert_null(op);
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ setup_write(void **state)
|
|||
/* ietf-netconf */
|
||||
fd = open(TESTS_DIR "/data/modules/ietf-netconf.yin", O_RDONLY);
|
||||
if (fd == -1) {
|
||||
free(w->session);
|
||||
free(w);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -46,8 +46,19 @@ typedef struct arg {
|
|||
struct nc_server_reply *
|
||||
rpc_clb(struct lyd_node *rpc, struct nc_session *session)
|
||||
{
|
||||
(void)rpc; (void)session;
|
||||
return nc_server_reply_ok();
|
||||
struct lyd_node *e;
|
||||
|
||||
(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 *
|
||||
|
@ -92,10 +103,14 @@ server_thread(void *arg)
|
|||
|
||||
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_free(ps);
|
||||
|
||||
/* Waiting for end of test */
|
||||
/* waiting for end of test */
|
||||
pthread_barrier_wait(&barrier);
|
||||
|
||||
nc_server_notif_free(notif);
|
||||
|
@ -110,7 +125,7 @@ notif_thread(void *arg)
|
|||
struct lyd_node *op;
|
||||
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);
|
||||
do {
|
||||
msgtype = nc_recv_notif(sess, 1000, &envp, &op);
|
||||
|
@ -131,44 +146,47 @@ main(void)
|
|||
struct nc_rpc *rpc;
|
||||
uint64_t msgid;
|
||||
NC_MSG_TYPE msgtype;
|
||||
const char *features[] = {"startup", NULL};
|
||||
const char *features[] = {"startup", "candidate", NULL};
|
||||
arg_t thread_arg;
|
||||
pthread_t t[2];
|
||||
char *str;
|
||||
|
||||
pthread_barrier_init(&barrier, 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 + 2) != -1);
|
||||
thread_arg.in = pipes[0];
|
||||
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_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, "module-a", NULL, NULL));
|
||||
thread_arg.ctx = server_ctx;
|
||||
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_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, "module-a", NULL, NULL));
|
||||
|
||||
/* Start server thread */
|
||||
/* start server thread */
|
||||
pthread_create(&t[0], NULL, server_thread, &thread_arg);
|
||||
nc_client_init();
|
||||
|
||||
/* Listen for notifications */
|
||||
/* listen for notifications */
|
||||
sess = nc_connect_inout(pipes[2], pipes[1], client_ctx);
|
||||
nc_assert(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);
|
||||
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);
|
||||
do {
|
||||
msgtype = nc_recv_reply(sess, rpc, msgid, 1000, &envp, &op);
|
||||
|
@ -177,12 +195,33 @@ main(void)
|
|||
nc_rpc_free(rpc);
|
||||
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_join(t[0], NULL);
|
||||
pthread_join(t[1], NULL);
|
||||
|
||||
/* Cleanup */
|
||||
/* cleanup */
|
||||
nc_session_free(sess, NULL);
|
||||
ly_ctx_destroy(server_ctx);
|
||||
ly_ctx_destroy(client_ctx);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue