diff --git a/CMakeLists.txt b/CMakeLists.txt index a3c18c4d..9eb242aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -251,8 +251,13 @@ if(ENABLE_SSH) include_directories(${LIBSSH_INCLUDE_DIRS}) # crypt - target_link_libraries(netconf2 -lcrypt) - list(APPEND CMAKE_REQUIRED_LIBRARIES crypt) + if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "QNX") + target_link_libraries(netconf2 -lcrypt) + list(APPEND CMAKE_REQUIRED_LIBRARIES crypt) + else() + target_link_libraries(netconf2 -llogin) + list(APPEND CMAKE_REQUIRED_LIBRARIES login) + endif() endif() # dependencies - libval @@ -268,6 +273,20 @@ find_package(LibYANG REQUIRED) target_link_libraries(netconf2 ${LIBYANG_LIBRARIES}) include_directories(${LIBYANG_INCLUDE_DIRS}) +# header file compatibility - shadow.h and crypt.h +check_include_file("shadow.h" HAVE_SHADOW) +check_include_file("crypt.h" HAVE_CRYPT) + +# function compatibility - getpeereid on QNX +if(${CMAKE_SYSTEM_NAME} MATCHES "QNX") + target_link_libraries(netconf2 -lsocket) + list(APPEND CMAKE_REQUIRED_LIBRARIES socket) + list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES pthread) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_QNX_SOURCE) + check_symbol_exists(getpeereid "sys/types.h;unistd.h" HAVE_GETPEEREID) + list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D_QNX_SOURCE) +endif() + # generate doxygen documentation for libnetconf2 API find_package(Doxygen) if(DOXYGEN_FOUND) diff --git a/src/config.h.in b/src/config.h.in index b69c8bd3..0f0bbcc3 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -47,6 +47,21 @@ */ #cmakedefine HAVE_PTHREAD_MUTEX_TIMEDLOCK +/* + * Support for getpeereid + */ +#cmakedefine HAVE_GETPEEREID + +/* + * Support for shadow file manipulation + */ +#cmakedefine HAVE_SHADOW + +/* + * Support for crypt.h + */ +#cmakedefine HAVE_CRYPT + /* * Location of installed basic YIN/YANG schemas */ diff --git a/src/session_server.c b/src/session_server.c index 38f28198..7b915958 100644 --- a/src/session_server.c +++ b/src/session_server.c @@ -11,6 +11,7 @@ * * https://opensource.org/licenses/BSD-3-Clause */ +#define _QNX_SOURCE /* getpeereid */ #define _GNU_SOURCE /* signals, threads, SO_PEERCRED */ #include @@ -1717,27 +1718,48 @@ nc_ps_clear(struct nc_pollsession *ps, int all, void (*data_free)(void *)) #if defined(NC_ENABLED_SSH) || defined(NC_ENABLED_TLS) +static int +nc_get_uid(int sock, uid_t *uid) +{ + #ifdef SO_PEERCRED + struct ucred ucred; + socklen_t len; + len = sizeof(ucred); + if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) { + ERR("Failed to get credentials from unix socket (%s).", + strerror(errno)); + close(sock); + return -1; + } + *uid = ucred.uid; + #else + if (getpeereid(sock, uid, NULL) < 0) { + ERR("Failed to get credentials from unix socket (%s).", + strerror(errno)); + close(sock); + return -1; + } + #endif + + return 0; +} + static int nc_accept_unix(struct nc_session *session, int sock) { -#ifdef SO_PEERCRED +#if defined(SO_PEERCRED) || defined(HAVE_GETPEEREID) const struct passwd *pw; - struct ucred ucred; char *username; - socklen_t len; session->ti_type = NC_TI_UNIX; + uid_t uid; - len = sizeof(ucred); - if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) { - ERR("Failed to get credentials from unix socket (%s).", - strerror(errno)); - close(sock); + if (nc_get_uid(sock, &uid) < 0) { return -1; } - pw = getpwuid(ucred.uid); + pw = getpwuid(uid); if (pw == NULL) { - ERR("Failed to find username for uid=%u (%s).\n", ucred.uid, + ERR("Failed to find username for uid=%u (%s).\n", uid, strerror(errno)); close(sock); return -1; diff --git a/src/session_server_ssh.c b/src/session_server_ssh.c index 412fbac0..215d2c67 100644 --- a/src/session_server_ssh.c +++ b/src/session_server_ssh.c @@ -14,21 +14,25 @@ #define _GNU_SOURCE +#include "config.h" /* Expose HAVE_SHADOW and HAVE_CRYPT */ + +#ifdef HAVE_SHADOW + #include +#endif +#ifdef HAVE_CRYPT + #include +#endif + #include #include #include #include #include -#ifndef __APPLE__ -#include -#include -#endif #include #include #include #include -#include "config.h" #include "session_server.h" #include "session_server_ch.h" #include "libnetconf.h" @@ -664,7 +668,7 @@ nc_server_ssh_clear_opts(struct nc_server_ssh_opts *opts) static char * auth_password_get_pwd_hash(const char *username) { -#ifndef __APPLE__ +#ifdef HAVE_SHADOW struct passwd *pwd, pwd_buf; struct spwd *spwd, spwd_buf; char *pass_hash = NULL, buf[256]; @@ -676,7 +680,11 @@ auth_password_get_pwd_hash(const char *username) } if (!strcmp(pwd->pw_passwd, "x")) { - getspnam_r(username, &spwd_buf, buf, 256, &spwd); + #ifndef __QNXNTO__ + getspnam_r(username, &spwd_buf, buf, 256, &spwd); + #else + spwd = getspnam_r(username, &spwd_buf, buf, 256); + #endif if (!spwd) { VRB("Failed to retrieve the shadow entry for \"%s\".", username); return NULL;