Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ set(CMAKE_MACOSX_RPATH TRUE)
# micro version is changed with a set of small changes or bugfixes anywhere in the project.
set(LIBNETCONF2_MAJOR_VERSION 4)
set(LIBNETCONF2_MINOR_VERSION 3)
set(LIBNETCONF2_MICRO_VERSION 4)
set(LIBNETCONF2_MICRO_VERSION 5)
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 5)
set(LIBNETCONF2_MINOR_SOVERSION 3)
set(LIBNETCONF2_MICRO_SOVERSION 10)
set(LIBNETCONF2_MICRO_SOVERSION 11)
set(LIBNETCONF2_SOVERSION_FULL ${LIBNETCONF2_MAJOR_SOVERSION}.${LIBNETCONF2_MINOR_SOVERSION}.${LIBNETCONF2_MICRO_SOVERSION})
set(LIBNETCONF2_SOVERSION ${LIBNETCONF2_MAJOR_SOVERSION})

Expand Down
4 changes: 2 additions & 2 deletions src/server_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,7 @@ int nc_server_config_del_tls_endpoint_client_ref(const char *endpt_name, struct
* @param[in] fingerprint Optional fingerprint of the entry. The fingerprint should always be set, however if it is
* not set, it will match any certificate. Entry with no fingerprint should therefore be placed only as the last entry.
* @param[in] map_type Mapping username to the certificate option.
* @param[in] name Username for this cert-to-name entry.
* @param[in] name Username for this cert-to-name entry. Mandatory if @p map_type is set to ::NC_TLS_CTN_SPECIFIED.
* @param[in,out] config Configuration YANG data tree. If *config is NULL, it will be created.
* Otherwise the new YANG data will be added to the previous data and may override it.
* @return 0 on success, non-zero otherwise.
Expand Down Expand Up @@ -1479,7 +1479,7 @@ int nc_server_config_del_ch_tls_ca_cert_truststore_ref(const char *client_name,
* @param[in] fingerprint Optional fingerprint of the entry. The fingerprint should always be set, however if it is
* not set, it will match any certificate. Entry with no fingerprint should therefore be placed only as the last entry.
* @param[in] map_type Mapping username to the certificate option.
* @param[in] name Username for this cert-to-name entry.
* @param[in] name Username for this cert-to-name entry. Mandatory if @p map_type is set to ::NC_TLS_CTN_SPECIFIED.
* @param[in,out] config Configuration YANG data tree. If *config is NULL, it will be created.
* Otherwise the new YANG data will be added to the previous data and may override it.
* @return 0 on success, non-zero otherwise.
Expand Down
17 changes: 11 additions & 6 deletions src/server_config_util_tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,10 @@ _nc_server_config_add_tls_ctn(const struct ly_ctx *ctx, const char *tree_path, c
int ret = 0;
const char *map;

NC_CHECK_ARG_RET(NULL, ctx, tree_path, name, config, 1);
if ((map_type == NC_TLS_CTN_SPECIFIED) && !name) {
ERR(NULL, "Client name must be provided for the \"specified\" CTN mapping type.");
return 1;
}

if (fingerprint) {
/* optional */
Expand All @@ -682,9 +685,11 @@ _nc_server_config_add_tls_ctn(const struct ly_ctx *ctx, const char *tree_path, c
goto cleanup;
}

ret = nc_server_config_append(ctx, tree_path, "name", name, config);
if (ret) {
goto cleanup;
if (name) {
ret = nc_server_config_append(ctx, tree_path, "name", name, config);
if (ret) {
goto cleanup;
}
}

cleanup:
Expand All @@ -698,7 +703,7 @@ nc_server_config_add_tls_ctn(const struct ly_ctx *ctx, const char *endpt_name, u
int ret = 0;
char *path = NULL;

NC_CHECK_ARG_RET(NULL, ctx, endpt_name, id, name, config, 1);
NC_CHECK_ARG_RET(NULL, ctx, endpt_name, id, config, 1);

ret = asprintf(&path, "/ietf-netconf-server:netconf-server/listen/endpoints/endpoint[name='%s']/tls/netconf-server-parameters/"
"client-identity-mappings/cert-to-name[id='%" PRIu32 "']", endpt_name, id);
Expand Down Expand Up @@ -736,7 +741,7 @@ nc_server_config_add_ch_tls_ctn(const struct ly_ctx *ctx, const char *client_nam
int ret = 0;
char *path = NULL;

NC_CHECK_ARG_RET(NULL, ctx, client_name, endpt_name, id, name, config, 1);
NC_CHECK_ARG_RET(NULL, ctx, client_name, endpt_name, id, config, 1);

ret = asprintf(&path, "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='%s']/"
"endpoints/endpoint[name='%s']/tls/netconf-server-parameters/client-identity-mappings/"
Expand Down
149 changes: 126 additions & 23 deletions src/session_mbedtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,37 +587,125 @@ nc_tls_cert_dup(const mbedtls_x509_crt *cert)
}

/**
* @brief Duplicate a certificate and append it to a chain.
* @brief Duplicate a certificate and prepend it to a chain.
*
* @param[in] cert Certificate to duplicate and append.
* @param[in,out] chain Chain to append the certificate to.
* @param[in] cert Certificate to duplicate and prepend.
* @param[in,out] chain Chain to prepend the certificate to.
* @return 0 on success, -1 on error.
*/
static int
nc_server_tls_append_cert_to_chain(mbedtls_x509_crt *cert, mbedtls_x509_crt **chain)
nc_server_tls_prepend_cert_to_chain(mbedtls_x509_crt *cert, mbedtls_x509_crt **chain)
{
mbedtls_x509_crt *iter, *copy;
mbedtls_x509_crt *copy;

copy = nc_tls_cert_dup(cert);
if (!copy) {
return -1;
}

if (!*chain) {
/* first in the list */
*chain = copy;
} else {
/* find the last cert */
iter = *chain;
while (iter->next) {
iter = iter->next;
copy->next = *chain;
*chain = copy;

return 0;
}

/**
* @brief Check whether a certificate is already present in a chain.
*
* @param[in] cert Certificate to search for.
* @param[in] chain Certificate chain.
* @return 1 if found, 0 otherwise.
*/
static int
nc_server_tls_cert_in_chain(const mbedtls_x509_crt *cert, const mbedtls_x509_crt *chain)
{
const mbedtls_x509_crt *iter;

for (iter = chain; iter; iter = iter->next) {
if (cert->raw.p && iter->raw.p && (cert->raw.len == iter->raw.len) && !memcmp(cert->raw.p, iter->raw.p, cert->raw.len)) {
return 1;
}
iter->next = copy;
}

return 0;
}

/**
* @brief Prepend issuer chain for a certificate.
*
* Repeatedly parse issuer_raw of @p cert into a certificate, then parse issuer_raw
* of that parsed issuer, and so on. Parsed issuers are prepended into @p chain in
* root-first order so that prepending the actual cert afterwards yields peer-first
* order.
*
* @param[in] cert Certificate whose issuers are to be prepended.
* @param[in,out] chain Chain to prepend issuer certificates to.
* @return 0 on success, -1 on error.
*/
static int
nc_server_tls_prepend_issuer_chain(mbedtls_x509_crt *cert, mbedtls_x509_crt **chain)
{
size_t i = 0;
mbedtls_x509_crt *copy;
const mbedtls_x509_crt *issuer, *iter, *cur;
mbedtls_x509_crt *issuers[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE - 1];

cur = cert;
while (cur && (i < (sizeof issuers / sizeof *issuers))) {
if (!cur->issuer_raw.p || !cur->issuer_raw.len) {
break;
}

if ((cur->issuer_raw.len == cur->subject_raw.len) && !memcmp(cur->issuer_raw.p, cur->subject_raw.p, cur->issuer_raw.len)) {
/* self-issued root reached */
break;
}

/* find issuer cert by matching issuer DN to subject DN */
issuer = NULL;
for (iter = cert; iter; iter = iter->next) {
if ((iter->subject_raw.len == cur->issuer_raw.len) &&
!memcmp(iter->subject_raw.p, cur->issuer_raw.p, cur->issuer_raw.len)) {
issuer = iter;
break;
}
}
if (!issuer) {
/* no more issuers available in the certificate set */
break;
}

if (nc_server_tls_cert_in_chain(issuer, *chain)) {
/* already present in chain */
break;
}

copy = nc_tls_cert_dup(issuer);
if (!copy) {
goto error;
}

issuers[i] = copy;
++i;
cur = issuer;
}

while (i) {
--i;
issuers[i]->next = *chain;
*chain = issuers[i];
}

return 0;

error:
while (i) {
--i;
nc_tls_cert_destroy_wrap(issuers[i]);
}
return -1;
}

/**
* @brief Verify a certificate.
*
Expand All @@ -634,11 +722,22 @@ nc_server_tls_verify_cb(void *cb_data, mbedtls_x509_crt *cert, int depth, uint32
struct nc_tls_verify_cb_data *data = cb_data;
char *err;

/* append to the chain we're building */
ret = nc_server_tls_append_cert_to_chain(cert, (mbedtls_x509_crt **)&data->chain);
if (ret) {
nc_tls_cert_destroy_wrap(data->chain);
return MBEDTLS_ERR_X509_ALLOC_FAILED;
if (!data->chain) {
/* first call, prepend the issuer chain so that we have the whole chain available for CTN */
ret = nc_server_tls_prepend_issuer_chain(cert, (mbedtls_x509_crt **)&data->chain);
if (ret) {
nc_tls_cert_destroy_wrap(data->chain);
return MBEDTLS_ERR_X509_ALLOC_FAILED;
}
}

/* prepend to the chain we're building to maintain peer-first order */
if (!nc_server_tls_cert_in_chain(cert, (const mbedtls_x509_crt *)data->chain)) {
ret = nc_server_tls_prepend_cert_to_chain(cert, (mbedtls_x509_crt **)&data->chain);
if (ret) {
nc_tls_cert_destroy_wrap(data->chain);
return MBEDTLS_ERR_X509_ALLOC_FAILED;
}
}

if (!*flags) {
Expand Down Expand Up @@ -836,18 +935,22 @@ nc_tls_get_num_certs_wrap(void *chain)
return n;
}

void
nc_tls_get_cert_wrap(void *chain, int idx, void **cert)
void *
nc_tls_get_cert_wrap(void *chain, int idx)
{
int i;
mbedtls_x509_crt *iter;

if (!chain || (idx < 0)) {
return NULL;
}

iter = chain;
for (i = 0; i < idx; i++) {
for (i = 0; iter && (i < idx); i++) {
iter = iter->next;
}

*cert = iter;
return iter;
}

int
Expand Down
10 changes: 7 additions & 3 deletions src/session_openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -616,10 +616,14 @@ nc_tls_get_num_certs_wrap(void *chain)
return sk_X509_num(chain);
}

void
nc_tls_get_cert_wrap(void *chain, int idx, void **cert)
void *
nc_tls_get_cert_wrap(void *chain, int idx)
{
*cert = sk_X509_value(chain, idx);
if (!chain || (idx < 0)) {
return NULL;
}

return sk_X509_value(chain, idx);
}

int
Expand Down
Loading