From d1f909b94efea6b1a03f22e8478de7937bfd4d43 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 30 Nov 2023 14:49:29 +0100 Subject: [PATCH 1/4] main UPDATE add back unix socket option Also call the ln2 api to create an unix endpoint instead of using the configuration data. --- CMakeLists.txt | 2 +- src/common.c | 2 +- src/common.h | 5 +++++ src/main.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- tests/np_test.c | 19 ++----------------- 5 files changed, 57 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a7e02ce7..7c10434f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,7 +54,7 @@ set(LIBYANG_DEP_SOVERSION 2.37.1) set(LIBYANG_DEP_SOVERSION_MAJOR 2) # libnetconf2 required version -set(LIBNETCONF2_DEP_VERSION 3.0.0) +set(LIBNETCONF2_DEP_VERSION 3.0.2) set(LIBNETCONF2_DEP_SOVERSION 4.0.0) set(LIBNETCONF2_DEP_SOVERSION_MAJOR 4) diff --git a/src/common.c b/src/common.c index 6e1ba156..ddf01e73 100644 --- a/src/common.c +++ b/src/common.c @@ -49,7 +49,7 @@ #include "log.h" #include "netconf_monitoring.h" -struct np2srv np2srv = {0}; +struct np2srv np2srv = {.unix_mode = -1, .unix_uid = -1, .unix_gid = -1}; int np_ignore_rpc(sr_session_ctx_t *ev_sess, sr_event_t event, int *rc) diff --git a/src/common.h b/src/common.h index 62287826..8df46d5f 100644 --- a/src/common.h +++ b/src/common.h @@ -69,6 +69,11 @@ struct np2srv { sr_subscription_ctx_t *sr_nacm_stats_sub; /**< sysrepo NACM global stats subscription context */ sr_subscription_ctx_t *sr_notif_sub; /**< sysrepo notification subscription context */ + const char *unix_path; /**< path to the UNIX socket to listen on */ + mode_t unix_mode; /**< UNIX socket mode */ + uid_t unix_uid; /**< UNIX socket UID */ + gid_t unix_gid; /**< UNIX socket GID */ + uint32_t sr_timeout; /**< timeout in ms for all sysrepo functions */ const char *ext_data_path; /**< path to the data file with data for LY ext data callback */ diff --git a/src/main.c b/src/main.c index e8dcf732..a615b88d 100644 --- a/src/main.c +++ b/src/main.c @@ -615,6 +615,14 @@ server_init(void) /* set libnetconf2 global PRC callback */ nc_set_global_rpc_clb(np2srv_rpc_cb); + /* UNIX socket */ + if (np2srv.unix_path) { + if (nc_server_add_endpt_unix_socket_listen("unix", np2srv.unix_path, np2srv.unix_mode, + np2srv.unix_uid, np2srv.unix_gid)) { + goto error; + } + } + /* restore a previous confirmed commit if restore file exists */ ncc_try_restore(); @@ -1061,6 +1069,8 @@ main(int argc, char *argv[]) int daemonize = 1, verb = 0; const char *pidfile = NP2SRV_PID_FILE_PATH; char *ptr; + struct passwd *pwd; + struct group *grp; struct sigaction action; sigset_t block_mask; @@ -1087,7 +1097,7 @@ main(int argc, char *argv[]) np2srv.server_dir = SERVER_DIR; /* process command line options */ - while ((c = getopt(argc, argv, "dFhVp:f:t:x:v:c:")) != -1) { + while ((c = getopt(argc, argv, "dFhVp:f:U::m:u:g:t:x:v:c:")) != -1) { switch (c) { case 'd': daemonize = 0; @@ -1138,6 +1148,43 @@ main(int argc, char *argv[]) case 'f': np2srv.server_dir = optarg; break; + case 'U': + /* optional argument */ + if (!optarg && (optind < argc) && (argv[optind][0] != '-')) { + /* assume the parameter is the optional argument */ + optarg = argv[optind++]; + } + np2srv.unix_path = optarg ? optarg : NP2SRV_UNIX_SOCK_PATH; + break; + case 'm': + np2srv.unix_mode = strtoul(optarg, &ptr, 8); + if (*ptr || (np2srv.unix_mode > 0777)) { + ERR("Invalid UNIX socket mode \"%s\".", optarg); + return EXIT_FAILURE; + } + break; + case 'u': + np2srv.unix_uid = strtoul(optarg, &ptr, 10); + if (*ptr) { + pwd = getpwnam(optarg); + if (!pwd) { + ERR("Invalid UNIX socket UID/user \"%s\".", optarg); + return EXIT_FAILURE; + } + np2srv.unix_uid = pwd->pw_uid; + } + break; + case 'g': + np2srv.unix_gid = strtoul(optarg, &ptr, 10); + if (*ptr) { + grp = getgrnam(optarg); + if (!grp) { + ERR("Invalid UNIX socket GID/group \"%s\".", optarg); + return EXIT_FAILURE; + } + np2srv.unix_gid = grp->gr_gid; + } + break; case 't': np2srv.sr_timeout = strtoul(optarg, &ptr, 10); if (*ptr) { diff --git a/tests/np_test.c b/tests/np_test.c index c320b012..dc46326e 100644 --- a/tests/np_test.c +++ b/tests/np_test.c @@ -232,7 +232,8 @@ np_glob_setup_np2(void **state, const char *test_name, const char **modules) close(fd); /* exec the server */ - execl(NP_BINARY_DIR "/netopeer2-server", NP_BINARY_DIR "/netopeer2-server", "-d", "-v3", "-t10", "-p", pidfile_path, "-f", server_dir, "-x", extdata_path, NULL); + execl(NP_BINARY_DIR "/netopeer2-server", NP_BINARY_DIR "/netopeer2-server", "-d", "-v3", "-t10", "-p", pidfile_path, + "-U", sock_path, "-m 600", "-f", server_dir, "-x", extdata_path, NULL); child_error: printf("Child execution failed\n"); @@ -283,22 +284,6 @@ np_glob_setup_np2(void **state, const char *test_name, const char **modules) return 1; } - /* prepare UNIX socket data for server configuration in the data store */ - if (sr_set_item_str(st->sr_sess, "/ietf-netconf-server:netconf-server/listen/endpoint[name='unix']/libnetconf2-netconf-server:unix-socket/path", sock_path, NULL, 0) != SR_ERR_OK) { - SETUP_FAIL_LOG; - return 1; - } - if (sr_set_item_str(st->sr_sess, "/ietf-netconf-server:netconf-server/listen/endpoint[name='unix']/libnetconf2-netconf-server:unix-socket/mode", "600", NULL, 0) != SR_ERR_OK) { - SETUP_FAIL_LOG; - return 1; - } - - /* apply the configuration */ - if (sr_apply_changes(st->sr_sess, 0)) { - SETUP_FAIL_LOG; - return 1; - } - /* acquire context */ if (!(st->ctx = sr_acquire_context(st->conn))) { SETUP_FAIL_LOG; From d2297d8d9473b1157ef2c160fe9b309a16950180 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 7 Dec 2023 10:59:05 +0100 Subject: [PATCH 2/4] cmake UPDATE install scripts to scripts folder --- CMakeLists.txt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c10434f..8bf986d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,7 +80,7 @@ option(ENABLE_URL "Enable URL capability" ON) set(THREAD_COUNT 3 CACHE STRING "Number of threads accepting new sessions and handling requests") set(POLL_IO_TIMEOUT 10 CACHE STRING "Timeout in milliseconds of polling sessions for new data. It is also used for synchronization of low level IO such as sending a reply while a notification is being sent") set(YANG_MODULE_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/yang/modules/netopeer2" CACHE STRING "Directory where to copy the YANG modules to") -set(SCRIPT_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/netopeer2" CACHE STRING "Directory where to copy the install scripts to") +set(DATA_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/netopeer2" CACHE STRING "Directory with shared netopeer2 data") # script options option(INSTALL_MODULES "Install required modules into sysrepo" ON) @@ -341,7 +341,8 @@ include_directories(${PROJECT_BINARY_DIR}) # install the modules and scripts install(DIRECTORY "${PROJECT_SOURCE_DIR}/modules/" DESTINATION ${YANG_MODULE_DIR}) -install(DIRECTORY "${PROJECT_SOURCE_DIR}/scripts/" DESTINATION ${SCRIPT_DIR} USE_SOURCE_PERMISSIONS) +install(DIRECTORY "${PROJECT_SOURCE_DIR}/scripts/" DESTINATION ${DATA_DIR}/scripts USE_SOURCE_PERMISSIONS) +install(DIRECTORY "${PROJECT_SOURCE_DIR}/pam/" DESTINATION ${DATA_DIR}/pam USE_SOURCE_PERMISSIONS) # install the binary, required modules, and default configuration install(TARGETS netopeer2-server DESTINATION ${CMAKE_INSTALL_SBINDIR}) @@ -359,7 +360,7 @@ if(INSTALL_MODULES) set(ENV{LN2_MODULE_DIR} \"${LN2_YANG_MODULE_DIR}\") set(ENV{SYSREPOCTL_EXECUTABLE} \"${SYSREPOCTL_EXECUTABLE}\") set(ENV{SYSREPOCFG_EXECUTABLE} \"${SYSREPOCFG_EXECUTABLE}\") - execute_process(COMMAND \"\$ENV{DESTDIR}${SCRIPT_DIR}/setup.sh\" RESULT_VARIABLE SETUP_RES) + execute_process(COMMAND \"\$ENV{DESTDIR}${DATA_DIR}/scripts/setup.sh\" RESULT_VARIABLE SETUP_RES) if(NOT SETUP_RES EQUAL \"0\") message(FATAL_ERROR \" scripts/setup.sh failed: \${SETUP_RES}\") endif() @@ -373,7 +374,7 @@ if(GENERATE_HOSTKEY) message(STATUS \"Generating a new RSA host key \\\"genkey\\\" if not already added...\") set(ENV{SYSREPOCTL_EXECUTABLE} \"${SYSREPOCTL_EXECUTABLE}\") set(ENV{SYSREPOCFG_EXECUTABLE} \"${SYSREPOCFG_EXECUTABLE}\") - execute_process(COMMAND \"\$ENV{DESTDIR}${SCRIPT_DIR}/merge_hostkey.sh\" RESULT_VARIABLE MERGE_HOSTKEY_RES) + execute_process(COMMAND \"\$ENV{DESTDIR}${DATA_DIR}/scripts/merge_hostkey.sh\" RESULT_VARIABLE MERGE_HOSTKEY_RES) if(NOT MERGE_HOSTKEY_RES EQUAL \"0\") message(FATAL_ERROR \" scripts/merge_hostkey.sh failed: \${MERGE_HOSTKEY_RES}\") endif() @@ -384,7 +385,7 @@ if(MERGE_LISTEN_CONFIG) message(STATUS \"Merging default server listen configuration if there is none...\") set(ENV{SYSREPOCTL_EXECUTABLE} \"${SYSREPOCTL_EXECUTABLE}\") set(ENV{SYSREPOCFG_EXECUTABLE} \"${SYSREPOCFG_EXECUTABLE}\") - execute_process(COMMAND \"\$ENV{DESTDIR}${SCRIPT_DIR}/merge_config.sh\" RESULT_VARIABLE MERGE_CONFIG_RES) + execute_process(COMMAND \"\$ENV{DESTDIR}${DATA_DIR}/scripts/merge_config.sh\" RESULT_VARIABLE MERGE_CONFIG_RES) if(NOT MERGE_CONFIG_RES EQUAL \"0\") message(FATAL_ERROR \" scripts/merge_config.sh failed: \${MERGE_CONFIG_RES}\") endif() @@ -417,7 +418,7 @@ add_custom_target(cleancache ) # uninstall -add_custom_target(uninstall ${SCRIPT_DIR}/remove.sh +add_custom_target(uninstall ${DATA_DIR}/scripts/remove.sh COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_MODULE_PATH}/uninstall.cmake" COMMENT "Removing netopeer2 modules from sysrepo..." ) From 6dc77fe07c05333162c826a5158124b50ace192e Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 7 Dec 2023 11:09:17 +0100 Subject: [PATCH 3/4] main UPDATE add system authentication --- CMakeLists.txt | 4 ++-- pam/netopeer2.conf | 11 +++++++++++ scripts/merge_config.sh | 20 +++++++------------- scripts/remove.sh | 6 ++++++ scripts/setup.sh | 12 ++++++++++++ src/main.c | 6 ++++++ 6 files changed, 44 insertions(+), 15 deletions(-) create mode 100644 pam/netopeer2.conf diff --git a/CMakeLists.txt b/CMakeLists.txt index 8bf986d2..944d89fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,8 +54,8 @@ set(LIBYANG_DEP_SOVERSION 2.37.1) set(LIBYANG_DEP_SOVERSION_MAJOR 2) # libnetconf2 required version -set(LIBNETCONF2_DEP_VERSION 3.0.2) -set(LIBNETCONF2_DEP_SOVERSION 4.0.0) +set(LIBNETCONF2_DEP_VERSION 3.0.3) +set(LIBNETCONF2_DEP_SOVERSION 4.1.0) set(LIBNETCONF2_DEP_SOVERSION_MAJOR 4) # sysrepo required version diff --git a/pam/netopeer2.conf b/pam/netopeer2.conf new file mode 100644 index 00000000..0bfdba97 --- /dev/null +++ b/pam/netopeer2.conf @@ -0,0 +1,11 @@ +#%PAM-1.0 +auth requisite pam_nologin.so +auth include common-auth +account requisite pam_nologin.so +account include common-account +password include common-password +session required pam_loginuid.so +session include common-session +session optional pam_keyinit.so force revoke +session optional pam_lastlog.so showfailed +session optional pam_motd.so diff --git a/scripts/merge_config.sh b/scripts/merge_config.sh index 36814380..da33feaf 100755 --- a/scripts/merge_config.sh +++ b/scripts/merge_config.sh @@ -68,19 +68,13 @@ if [ -f "$AUTHORIZED_KEYS_FILE" ]; then echo "-- Added user \"${CURRENT_USER}\" that can authenticate with a key pair from his authorized_keys to the server configuration..." echo "--" else - # authorized_keys doesn't exist, get the user's pw hash from /etc/shadow and use that for authentication - CURRENT_USER_PW_HASH=$(awk -v user="$CURRENT_USER" -F':' '$1 == user {print $2}' /etc/shadow) - if [ -n "$CURRENT_USER_PW_HASH" ]; then - # only add the user if his password hash is not empty - AUTH_CONFIG="${CURRENT_USER_PW_HASH}" - echo "--" - echo "-- Added user \"${CURRENT_USER}\" that can authenticate with his password to the server configuration..." - echo "--" - else - echo "--" - echo "-- No user was added to the server configuration, you will need to add one manually..." - echo "--" - fi + # authorized_keys file doesn't exist, leave the authentication to the system + AUTH_CONFIG=" + + " + echo "--" + echo "-- Added user \"${CURRENT_USER}\" that can authenticate with his password to the server configuration..." + echo "--" fi if [ -n "$AUTH_CONFIG" ]; then diff --git a/scripts/remove.sh b/scripts/remove.sh index 8cfbbdf4..e3306fb0 100755 --- a/scripts/remove.sh +++ b/scripts/remove.sh @@ -70,3 +70,9 @@ SCTL_MODULES=`$SYSREPOCTL -l` # uninstall np2 and ln2 modules UNINSTALL_CMD "${NP2_MODULES[@]}" UNINSTALL_CMD "${LN2_MODULES[@]}" + +# remove PAM service file if it exists +if [ -f "/etc/pam.d/netopeer2.conf" ]; then + echo "-- Removing PAM service file /etc/pam.d/netopeer2.conf" + rm /etc/pam.d/netopeer2.conf +fi diff --git a/scripts/setup.sh b/scripts/setup.sh index 02c1b10c..04fd0841 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -140,3 +140,15 @@ if [ ! -z "${CMD_INSTALL}" ]; then exit $rc fi fi + +# copy the PAM service file to /etc/pam.d +if [ ! -d "/etc/pam.d" ]; then + echo "-- Skipping PAM service file /etc/pam.d/netopeer2.conf, because directory /etc/pam.d not found" +elif [ -f "/etc/pam.d/netopeer2.conf" ]; then + echo "-- Skipping PAM service file /etc/pam.d/netopeer2.conf, because it already exists" +elif [ ! -w "/etc/pam.d" ]; then + echo "-- Skipping PAM service file /etc/pam.d/netopeer2.conf, because of no write permission" +else + echo "-- Installing PAM service file to /etc/pam.d/netopeer2.conf" + cp ../pam/netopeer2.conf /etc/pam.d/ +fi diff --git a/src/main.c b/src/main.c index a615b88d..2530d466 100644 --- a/src/main.c +++ b/src/main.c @@ -601,6 +601,12 @@ server_init(void) #ifdef NC_ENABLED_SSH_TLS /* set ln2 call home call backs and data */ nc_server_ch_set_dispatch_data(np2srv_acquire_ctx_cb, np2srv_release_ctx_cb, np2srv.sr_conn, np2srv_new_session_cb, NULL); + + /* set PAM service name */ + if (nc_server_ssh_set_pam_conf_filename("netopeer2.conf")) { + ERR("Setting PAM configuration filename failed."); + goto error; + } #endif /* NC_ENABLED_SSH_TLS */ /* set capabilities for the NETCONF Notifications */ From e9718cd2b31cd73856d5884d7601433a88f8fda1 Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 1 Dec 2023 13:22:38 +0100 Subject: [PATCH 4/4] VERSION bump to version 2.2.5 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 944d89fb..0022aa2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,7 +46,7 @@ endif() # Generic version of not only the library. Major version is reserved for really big changes of the project, # 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(NP2SRV_VERSION 2.2.4) +set(NP2SRV_VERSION 2.2.5) # libyang required version set(LIBYANG_DEP_VERSION 2.1.87)