Skip to content

Commit

Permalink
Merge branch 'devel-server'
Browse files Browse the repository at this point in the history
  • Loading branch information
michalvasko committed Sep 19, 2018
2 parents d3ae542 + ca0256d commit e17e029
Show file tree
Hide file tree
Showing 30 changed files with 1,043 additions and 756 deletions.
2 changes: 1 addition & 1 deletion cli/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ set(CMAKE_C_FLAGS_RELEASE "-O2")
set(CMAKE_C_FLAGS_DEBUG "-g -O0")

# set version
set(NP2CLI_VERSION 2.0.48)
set(NP2CLI_VERSION 2.0.49)
configure_file("${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_BINARY_DIR}/version.h" ESCAPE_QUOTES @ONLY)
include_directories(${PROJECT_BINARY_DIR})

Expand Down
2 changes: 1 addition & 1 deletion cli/commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -2402,7 +2402,7 @@ cmd_searchpath(const char *arg, char **UNUSED(tmp_config_file))

if (!arg[0]) {
path = nc_client_get_schema_searchpath();
fprintf(stdout, "%s\n", path[0] ? path : "<none>");
fprintf(stdout, "%s\n", path && path[0] ? path : "<none>");
return 0;
}

Expand Down
9 changes: 8 additions & 1 deletion keystored/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG")
set(CMAKE_C_FLAGS_DEBUG "-g -O0 -DDEBUG")

# set version
set(KEYSTORED_VERSION 0.1.1)
set(KEYSTORED_VERSION 0.1.2)

# config variables
if (NOT KEYSTORED_KEYS_DIR)
Expand Down Expand Up @@ -131,10 +131,17 @@ endif()

option(SSH_KEY_INSTALL "Enable ssh key import" ON)
if (SSH_KEY_INSTALL)
if (NOT SSH_KEYGEN_EXECUTABLE)
find_program(SSH_KEYGEN_EXECUTABLE ssh-keygen)
endif()
if (NOT SSH_KEYGEN_EXECUTABLE)
message(FATAL_ERROR "Unable to find ssh-keygen, set SSH_KEYGEN_EXECUTABLE manually.")
endif()
install(CODE "
set(ENV{SYSREPOCFG} ${SYSREPOCFG_EXECUTABLE})
set(ENV{CHMOD} ${CHMOD_EXECUTABLE})
set(ENV{OPENSSL} ${OPENSSL_EXECUTABLE})
set(ENV{SSH_KEYGEN} ${SSH_KEYGEN_EXECUTABLE})
set(ENV{KEYSTORED_KEYS_DIR} ${KEYSTORED_KEYS_DIR})
set(ENV{KEYSTORED_CHECK_SSH_KEY} ${KEYSTORED_CHECK_SSH_KEY})
execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/scripts/ssh-key-import.sh)")
Expand Down
8 changes: 4 additions & 4 deletions keystored/keystored.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ ks_cert_change_cb(sr_session_ctx_t *UNUSED(session), const char *UNUSED(module_n
}

static int
ks_privkey_get_cb(const char *xpath, sr_val_t **values, size_t *values_cnt, void *UNUSED(private_ctx))
ks_privkey_get_cb(const char *xpath, sr_val_t **values, size_t *values_cnt, uint64_t UNUSED(request_id), void *UNUSED(private_ctx))
{
int ret;
const char *name;
Expand All @@ -137,7 +137,7 @@ ks_privkey_get_cb(const char *xpath, sr_val_t **values, size_t *values_cnt, void
}
name += 18;

if (asprintf(&path, "%s/%.*s.pub.pem", KEYSTORED_KEYS_DIR, (int)(strchr(name, '\'') - name), name) == -1) {
if (asprintf(&path, "%s/%.*s.pem.pub", KEYSTORED_KEYS_DIR, (int)(strchr(name, '\'') - name), name) == -1) {
SRP_LOG_ERR("Memory allocation failed (%s:%d).", __FILE__, __LINE__);
return SR_ERR_NOMEM;
}
Expand Down Expand Up @@ -337,7 +337,7 @@ ks_privkey_gen_cb(const char *UNUSED(xpath), const sr_node_t *input, const size_
goto cleanup;
}
sprintf(priv_path, "%s/%s.pem", KEYSTORED_KEYS_DIR, input[0].data.string_val);
sprintf(pub_path, "%s/%s.pub.pem", KEYSTORED_KEYS_DIR, input[0].data.string_val);
sprintf(pub_path, "%s/%s.pem.pub", KEYSTORED_KEYS_DIR, input[0].data.string_val);

if (!(pid = fork())) {
/* child */
Expand Down Expand Up @@ -451,7 +451,7 @@ ks_privkey_load_cb(const char *UNUSED(xpath), const sr_node_t *input, const size
goto cleanup;
}
sprintf(priv_path, "%s/%s.pem", KEYSTORED_KEYS_DIR, input[0].data.string_val);
sprintf(pub_path, "%s/%s.pub.pem", KEYSTORED_KEYS_DIR, input[0].data.string_val);
sprintf(pub_path, "%s/%s.pem.pub", KEYSTORED_KEYS_DIR, input[0].data.string_val);

fd = open(priv_path, O_CREAT | O_TRUNC | O_WRONLY, 00600);
if (fd == -1) {
Expand Down
14 changes: 8 additions & 6 deletions keystored/scripts/ssh-key-import.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ local_path=$(dirname $0)
: ${SYSREPOCFG:=sysrepocfg}
: ${CHMOD:=chmod}
: ${OPENSSL:=openssl}
: ${SSH_KEYGEN:=ssh-keygen}
: ${STOCK_KEY_CONFIG:=$local_path/../stock_key_config.xml}
: ${KEYSTORED_KEYS_DIR:=/etc/keystored/keys}

Expand All @@ -21,13 +22,14 @@ if [ $KEYSTORED_CHECK_SSH_KEY -eq 0 ]; then
echo "- Warning: Assuming that an external script will provide the SSH key in a PEM format at \"${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem\"."
echo "- Importing ietf-keystore stock key configuration..."
$SYSREPOCFG -d startup -i ${STOCK_KEY_CONFIG} ietf-keystore
elif [ -r /etc/ssh/ssh_host_rsa_key ]; then
cp /etc/ssh/ssh_host_rsa_key ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem
else
if [ -r ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem -a -r ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem.pub ]; then
echo "- SSH hostkey found, no need to generate a new one."
else
echo "- SSH hostkey not found, generating a new one..."
$SSH_KEYGEN -m pem -t rsa -q -N "" -f ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem
fi
$CHMOD go-rw ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem
$OPENSSL rsa -pubout -in ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pem \
-out ${KEYSTORED_KEYS_DIR}/ssh_host_rsa_key.pub.pem
echo "- Importing ietf-keystore stock key configuration..."
$SYSREPOCFG -d startup -i ${STOCK_KEY_CONFIG} ietf-keystore
else
echo "- Warning: Cannot read the SSH hostkey at /etc/ssh/ssh_host_rsa_key, skipping."
fi
9 changes: 7 additions & 2 deletions server/CMakeLists.txt
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ if(NOT UNIX)
endif()

# set version
set(NP2SRV_VERSION 0.5.31)
set(NP2SRV_VERSION 0.6.15)

# set default build type if not specified by user
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE debug)
endif()

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -std=gnu11")
set(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG")
set(CMAKE_C_FLAGS_DEBUG "-g -O0 -DDEBUG")

Expand All @@ -36,6 +36,11 @@ option(ENABLE_CONFIGURATION "Enable server configuration" ON)
set(THREAD_COUNT 5 CACHE STRING "Number of threads accepting new sessions and handling requests")
set(DEFAULT_HOST_KEY "/etc/ssh/ssh_host_rsa_key" CACHE STRING "Default server host key (used only if configuration is disabled)")

option(ENABLE_LY_CTX_INFO_CACHE "Enable caching the ly_ctx_info() result; reduces processing at the cost of increased memory usage." ON)
if(ENABLE_LY_CTX_INFO_CACHE)
set(NP2SRV_ENABLED_LY_CTX_INFO_CACHE 1)
endif()

# set prefix for the PID file
if (NOT PIDFILE_PREFIX)
set(PIDFILE_PREFIX "/var/run")
Expand Down
8 changes: 8 additions & 0 deletions server/KNOWNISSUES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,11 @@ pthread_rwlockattr_setkind_np() and the number of worker threads is increased
(via cmake THREAD_COUNT variable), the thread processing the modules changes in
sysrepo (module install/uninstall or feature changes) can starve by waiting
for lock to wite changes into the netopeer's context.

XPath filter limitations
------------------------

Correct filter result is guaranteed only when all the filtered nodes
are only from one YANG schema and no unions are used. Otherwise,
the <get> or <get-config> may finish with an error or possibly
less data than would be correct.
4 changes: 4 additions & 0 deletions server/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ struct np2srv {
pthread_t workers[NP2SRV_THREAD_COUNT]; /**< worker threads handling sessions */

struct ly_ctx *ly_ctx; /**< libyang's context */
#ifdef NP2SRV_ENABLED_LY_CTX_INFO_CACHE
uint16_t cached_ly_ctx_module_set_id; /**< module-set-id at the time ly_ctx_info was last cached */
struct lyd_node *ly_ctx_info_cache; /**< a cache of calling ly_ctx_info on the ly_ctx */
#endif
pthread_rwlock_t ly_ctx_lock; /**< libyang's context rwlock */
};
extern struct np2srv np2srv;
Expand Down
4 changes: 4 additions & 0 deletions server/config.h.in
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,8 @@
*/
#define NP2SRV_SR_LOCKED_RETRIES 3

/** @brief Enable caching the ly_ctx_info() result
*/
#cmakedefine NP2SRV_ENABLED_LY_CTX_INFO_CACHE

#endif /* NP2SRV_CONFIG_H_ */
51 changes: 51 additions & 0 deletions server/ietf_keystore.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,57 @@ np_server_cert_clb(const char *name, void *UNUSED(user_data), char **UNUSED(cert
return 0;
}

int
np_server_cert_chain_clb(const char *name, void *UNUSED(user_data), char ***UNUSED(cert_paths), int *UNUSED(cert_path_count),
char ***cert_data, int *cert_data_count)
{
int ret;
char *path;
sr_val_t *sr_certs;
size_t sr_cert_count, i, used_count;

ret = asprintf(&path, "/ietf-keystore:keystore/private-keys/private-key/certificate-chains/"
"certificate-chain[name='%s']/certificate", name);
if (ret == -1) {
EMEM;
return 1;
}

if (np2srv.sr_sess.ds != SR_DS_RUNNING) {
if (np2srv_sr_session_switch_ds(np2srv.sr_sess.srs, SR_DS_RUNNING, NULL)) {
free(path);
return 1;
}
np2srv.sr_sess.ds = SR_DS_RUNNING;
}

/* Refresh the session to prevent sysrepo returning cached data */
if (np2srv_sr_session_refresh(np2srv.sr_sess.srs, NULL)) {
ERR("%s:%d Failed session refresh", __func__, __LINE__);
free(path);
return 1;
}

if (np2srv_sr_get_items(np2srv.sr_sess.srs, path, &sr_certs, &sr_cert_count, NULL)) {
free(path);
return 1;
}
free(path);

/* Ignore the first cert since it's already loaded */
if (sr_cert_count > 1) {
used_count = sr_cert_count - 1;
*cert_data = calloc(used_count, sizeof **cert_data);
for (i = 0; i < used_count; ++i) {
(*cert_data)[i] = strdup(sr_certs[i + 1].data.binary_val);
}
*cert_data_count = used_count;
}

sr_free_values(sr_certs, sr_cert_count);
return 0;
}

int
np_trusted_cert_list_clb(const char *name, void *UNUSED(user_data), char ***UNUSED(cert_paths), int *UNUSED(cert_path_count),
char ***cert_data, int *cert_data_count)
Expand Down
3 changes: 3 additions & 0 deletions server/ietf_keystore.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ int np_hostkey_clb(const char *name, void *user_data, char **privkey_path, char
int np_server_cert_clb(const char *name, void *user_data, char **cert_path, char **cert_data, char **privkey_path,
char **privkey_data, int *privkey_data_rsa);

int np_server_cert_chain_clb(const char *name, void *user_data, char ***cert_paths, int *cert_path_count,
char ***cert_data, int *cert_data_count);

int np_trusted_cert_list_clb(const char *name, void *user_data, char ***cert_paths, int *cert_path_count,
char ***cert_data, int *cert_data_count);

Expand Down
1 change: 1 addition & 0 deletions server/ietf_netconf_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -1241,6 +1241,7 @@ ietf_netconf_server_init(const struct lys_module *module)
nc_server_ssh_set_hostkey_clb(np_hostkey_clb, NULL, NULL);
#ifdef NC_ENABLED_TLS
nc_server_tls_set_server_cert_clb(np_server_cert_clb, NULL, NULL);
nc_server_tls_set_server_cert_chain_clb(np_server_cert_chain_clb, NULL, NULL);
nc_server_tls_set_trusted_cert_list_clb(np_trusted_cert_list_clb, NULL, NULL);
#endif

Expand Down
74 changes: 61 additions & 13 deletions server/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,18 +222,13 @@ signal_handler(int sig)
}
}

static int
np2srv_module_assign_clbs(const struct lys_module *mod)
static void
np2srv_node_assign_clbs(struct lys_node *start)
{
struct lys_node *snode, *next;

if (!strcmp(mod->name, "ietf-netconf-monitoring") || !strcmp(mod->name, "ietf-netconf")) {
/* skip it, use internal implementations from libnetconf2 */
return EXIT_SUCCESS;
}

/* set RPC and Notifications callbacks */
LY_TREE_DFS_BEGIN(mod->data, next, snode) {
LY_TREE_DFS_BEGIN(start, next, snode) {
if (snode->nodetype & (LYS_RPC | LYS_ACTION)) {
nc_set_rpc_callback(snode, op_generic);
goto dfs_nextsibling;
Expand Down Expand Up @@ -262,6 +257,24 @@ np2srv_module_assign_clbs(const struct lys_module *mod)
}
}

}

static int
np2srv_module_assign_clbs(const struct lys_module *mod)
{
if (!strcmp(mod->name, "ietf-netconf-monitoring") || !strcmp(mod->name, "ietf-netconf")) {
/* skip it, use internal implementations from libnetconf2 */
return EXIT_SUCCESS;
}
np2srv_node_assign_clbs(mod->data);
for (uint8_t i = 0; i < mod->augment_size; ++i) {
struct lys_node *target = mod->augment[i].target;
if (!strcmp(target->module->name, "ietf-netconf-monitoring") || !strcmp(target->module->name, "ietf-netconf")) {
continue;
}
np2srv_node_assign_clbs(target);
}

return EXIT_SUCCESS;
}

Expand Down Expand Up @@ -323,13 +336,19 @@ np2srv_verify_clb(const struct nc_session *session)
return 1;
}

static char *
static void free_with_user_data(void *data, void *user_data)
{
free(data);
(void)user_data;
}

static const char *
np2srv_ly_import_clb(const char *mod_name, const char *mod_rev, const char *submod_name, const char *submod_rev,
void *UNUSED(user_data), LYS_INFORMAT *format, void (**free_module_data)(void *model_data))
void *UNUSED(user_data), LYS_INFORMAT *format, void (**free_module_data)(void *model_data, void *user_data))
{
char *data = NULL;

*free_module_data = free;
*free_module_data = free_with_user_data;
*format = LYS_YIN;
if (submod_rev || (submod_name && !mod_name)) {
np2srv_sr_get_submodule_schema(np2srv.sr_sess.srs, submod_name, submod_rev, SR_SCHEMA_YIN, &data, NULL);
Expand Down Expand Up @@ -421,6 +440,18 @@ np2srv_create_capab(const struct lys_module *mod)
return cpb;
}

#ifdef NP2SRV_ENABLED_LY_CTX_INFO_CACHE
static void
np2srv_update_ly_ctx_info_cache(uint16_t module_set_id)
{
if (np2srv.ly_ctx_info_cache) {
lyd_free_withsiblings(np2srv.ly_ctx_info_cache);
}
np2srv.cached_ly_ctx_module_set_id = module_set_id;
np2srv.ly_ctx_info_cache = ly_ctx_info(np2srv.ly_ctx);
}
#endif

static void
np2srv_module_install_clb(const char *module_name, const char *revision, sr_module_state_t state, void *UNUSED(private_ctx))
{
Expand Down Expand Up @@ -544,19 +575,30 @@ np2srv_feature_change_clb(const char *module_name, const char *feature_name, boo
}

static int
np2srv_state_data_clb(const char *xpath, sr_val_t **values, size_t *values_cnt, void *UNUSED(private_ctx))
np2srv_state_data_clb(const char *xpath, sr_val_t **values, size_t *values_cnt, uint64_t UNUSED(request_id), void *UNUSED(private_ctx))
{
struct lyd_node *data = NULL, *node, *iter;
struct ly_set *set = NULL;
uint32_t i, j;
bool should_free_data = true;
int ret = SR_ERR_OK;

if (!strncmp(xpath, "/ietf-netconf-monitoring:", 25)) {
data = ncm_get_data();
} else if (!strncmp(xpath, "/nc-notifications:", 18)) {
data = ntf_get_data();
} else if (!strncmp(xpath, "/ietf-yang-library:", 19)) {
#ifdef NP2SRV_ENABLED_LY_CTX_INFO_CACHE
uint16_t module_set_id = ly_ctx_get_module_set_id(np2srv.ly_ctx);
if (module_set_id != np2srv.cached_ly_ctx_module_set_id) {
np2srv_update_ly_ctx_info_cache(module_set_id);
}

data = np2srv.ly_ctx_info_cache;
should_free_data = false;
#else
data = ly_ctx_info(np2srv.ly_ctx);
#endif
} else {
ret = SR_ERR_OPERATION_FAILED;
goto cleanup;
Expand Down Expand Up @@ -623,7 +665,9 @@ np2srv_state_data_clb(const char *xpath, sr_val_t **values, size_t *values_cnt,

cleanup:
ly_set_free(set);
lyd_free_withsiblings(data);
if (should_free_data) {
lyd_free_withsiblings(data);
}
if (ret != SR_ERR_OK) {
sr_free_values(*values, *values_cnt);
*values_cnt = 0;
Expand Down Expand Up @@ -1573,6 +1617,10 @@ main(int argc, char *argv[])
}
nc_ps_free(np2srv.nc_ps);

#ifdef NP2SRV_ENABLED_LY_CTX_INFO_CACHE
lyd_free_withsiblings(np2srv.ly_ctx_info_cache);
#endif

/* clears all the sessions also */
sr_disconnect(np2srv.sr_conn);

Expand Down
Loading

0 comments on commit e17e029

Please sign in to comment.