aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlns <matzeton@googlemail.com>2018-07-19 22:00:12 +0200
committerlns <matzeton@googlemail.com>2018-07-19 22:00:12 +0200
commit169fc69a9d0f3b213fabf57e4d9b49bd3eacdc76 (patch)
tree7f90832ac63cfc1ca5929ff2df00a5f97f692b7e
parent0a582bc2086e98302f7da2a2e6b128cca6d3b444 (diff)
added compat module and functions
Signed-off-by: lns <matzeton@googlemail.com>
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--.travis.yml3
-rw-r--r--configure.ac2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/compat.c104
-rw-r--r--src/compat.h55
-rw-r--r--src/filesystem.c11
-rw-r--r--src/log.c7
-rw-r--r--src/main.c4
-rw-r--r--src/protocol_ssh.c36
-rw-r--r--src/utils.c60
11 files changed, 233 insertions, 53 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b3c929d..c570823 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -66,4 +66,4 @@ cppcheck:
stage: analysis
script:
- pacman -Syu --noconfirm cppcheck
- - cppcheck --enable=all --inconclusive --std=posix .
+ - cppcheck --force --enable=warning,unusedFunction,performance,portability --inconclusive --std=posix -DNDEBUG=1 -DHAVE_STRTOK_R=1 -DHAVE_LOCALTIME_R=1 -DHAVE_GETPWNAM_R=1 -DHAVE_GETGRNAM_R=1 .
diff --git a/.travis.yml b/.travis.yml
index 69b2f98..6f43ffe 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,7 @@ compiler:
- gcc
before_install:
- sudo apt-get -qq update
-- sudo apt-get install -y -qq coreutils make autoconf automake gcc pkg-config valgrind
+- sudo apt-get install -y -qq coreutils make autoconf automake gcc pkg-config valgrind cppcheck
wget libssl-dev
- wget 'https://www.libssh.org/files/0.7/libssh-0.7.5.tar.xz' -O ./libssh-0.7.5.tar.xz
- tar -xvf ./libssh-0.7.5.tar.xz
@@ -21,6 +21,7 @@ script:
- TERM=linux valgrind --error-exitcode=1 ./src/potd --test --redirect 127.0.0.1:2222:127.0.0.1:22222
--protocol 127.0.0.1:22222:127.0.0.1:33333 --jail 127.0.0.1:33333 --rofile /tmp/potd-rofile
--rodir /tmp/potd-rodir --root / --netns-rundir /tmp/potd-netns --ssh-rundir /tmp/potd-ssh
+- cppcheck --force --enable=warning,unusedFunction,performance,portability --inconclusive --std=posix -DNDEBUG=1 -DHAVE_STRTOK_R=1 -DHAVE_LOCALTIME_R=1 -DHAVE_GETPWNAM_R=1 -DHAVE_GETGRNAM_R=1 .
env:
global:
secure: ZWiQ1tSucEHu8V1qajVPOi7mpqdQ2horCuRdjJJcU6zT+//HOcApsKS/zexLMwTSgazzYSVZXpakjW7PTWpo6MJWDyDyXKHL6yWpVaYlyieUjbvnidooYIn9kcqVi4yuEk3dGorRFcaVujHkLQyq4WtmrxtKQD7iepFJ5rDUHBTOHeeY+zhv3+gPWCeIMOB//0Df4KYd3rfPICmRMALrRYBXr9xX4UBF5BeIFgGFO6Y+j/Pr9LWrqTpAyShREs0QAn7f8ZUGtG9igNhueaDnjNe6Zi5Pl2XTd0R+YIBl/b6AlLtWbnf8MUoyNzy6wJkI9DThJXGpdItlE9/Jf1mDt3qvmdGfDFWL4HnflSVrmKl7TCfx4etHelU2BArhBp/PzvxYwIhMVv+cqmWv7DVtmWRDN/O9rqe1+g5Dy6I5t05t8ZbcLASDwVS9sa4+jwtLJMxLgySMQ2I2AihvrxYkRdahIYd4V7Ge9Gy8M8xPEkQa0riYb6phD4cx5FQY1oP9zpZMHKsF98aKMqAQOffwrwRe2hrJxxlo2anBSxs7y0fn33PrjX5r3orEMiPJ3mhuwMofxdxrKx9oBBiWmMYC2it3l/rNzHMYDNs/weKro8guTXRWwzRB7oeFJq9sEXbdtN4WoG4dXTYxsE/rHZStIcPgKFPJSwoSq6WIHYlh1wI=
diff --git a/configure.ac b/configure.ac
index bd51074..f97323d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -135,6 +135,8 @@ AC_CHECK_FUNCS([open read write close mmap munmap malloc free memset memcpy fork
setsockopt socket connect accept bind listen \
time localtime difftime strtol strtoll getopt_long_only], [],
[ AC_MSG_ERROR([required function not available]) ])
+dnl check reentrant function availability
+AC_CHECK_FUNCS([strtok_r localtime_r getpwnam_r getgrnam_r])
dnl GAI functions
AC_CHECK_FUNCS([getaddrinfo getnameinfo freeaddrinfo], [],
[ AC_MSG_ERROR([required GAI function not available]) ])
diff --git a/src/Makefile.am b/src/Makefile.am
index 1ac657b..c2fe07c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,5 +1,5 @@
sbin_PROGRAMS = potd
-potd_SOURCES = utils.c options.c log.c log_colored.c log_file.c socket.c pevent.c capabilities.c filesystem.c jail.c forward.c redirector.c protocol.c protocol_ssh.c main.c
+potd_SOURCES = compat.c utils.c options.c log.c log_colored.c log_file.c socket.c pevent.c capabilities.c filesystem.c jail.c forward.c redirector.c protocol.c protocol_ssh.c main.c
if HAVE_SECCOMP
potd_SOURCES += pseccomp.c
endif
diff --git a/src/compat.c b/src/compat.c
new file mode 100644
index 0000000..72c78a3
--- /dev/null
+++ b/src/compat.c
@@ -0,0 +1,104 @@
+/*
+ * compat.c
+ * potd is licensed under the BSD license:
+ *
+ * Copyright (c) 2018 Toni Uhlig <matzeton@googlemail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * - The names of its contributors may not be used to endorse or promote
+ * products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "compat.h"
+
+
+char *
+potd_strtok(char *str, const char *delim, char **saveptr)
+{
+#ifdef HAVE_STRTOK_R
+ return strtok_r(str, delim, saveptr);
+#else
+ (void) saveptr;
+
+ return strtok(str, delim);
+#endif
+}
+
+struct tm *
+potd_localtime(const time_t *timep, struct tm *result)
+{
+#ifdef HAVE_LOCALTIME_R
+ return localtime_r(timep, result);
+#else
+ (void) result;
+
+ return localtime(timep);
+#endif
+}
+
+int
+potd_getpwnam(const char *name, struct passwd *pwd)
+{
+ struct passwd *result = NULL;
+
+ errno = 0;
+#ifdef HAVE_GETPWNAM_R
+ char buf[BUFSIZ];
+
+ return getpwnam_r(name, pwd, buf, sizeof buf, &result) || !result;
+#else
+ result = getpwnam(name);
+ if (result)
+ *pwd = *result;
+
+ return result == NULL;
+#endif
+}
+
+int
+potd_getgrnam(const char *name, struct group *grp)
+{
+ struct group *result = NULL;
+
+ errno = 0;
+#ifdef HAVE_GETGRNAM_R
+ char buf[BUFSIZ];
+
+ return getgrnam_r(name, grp, buf, sizeof buf, &result) || !result;
+#else
+ result = getgrnam(name);
+ if (result)
+ *grp = *result;
+
+ return result == NULL;
+#endif
+}
diff --git a/src/compat.h b/src/compat.h
new file mode 100644
index 0000000..386b80e
--- /dev/null
+++ b/src/compat.h
@@ -0,0 +1,55 @@
+/*
+ * compat.h
+ * potd is licensed under the BSD license:
+ *
+ * Copyright (c) 2018 Toni Uhlig <matzeton@googlemail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * - The names of its contributors may not be used to endorse or promote
+ * products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef POTD_COMPAT_H
+#define POTD_COMPAT_H 1
+
+#include <string.h>
+#include <time.h>
+#include <pwd.h>
+#include <grp.h>
+
+
+char *
+potd_strtok(char *str, const char *delim, char **saveptr);
+
+struct tm *
+potd_localtime(const time_t *timep, struct tm *result);
+
+int
+potd_getpwnam(const char *name, struct passwd *pwd);
+
+int
+potd_getgrnam(const char *name, struct group *grp);
+
+#endif
diff --git a/src/filesystem.c b/src/filesystem.c
index 3284dd4..fa94987 100644
--- a/src/filesystem.c
+++ b/src/filesystem.c
@@ -49,6 +49,7 @@
#include <assert.h>
#include "log.h"
+#include "compat.h"
#include "utils.h"
#include "options.h"
@@ -239,7 +240,7 @@ static MountData *
get_last_mount(void)
{
FILE *fp = fopen("/proc/self/mountinfo", "r");
- char *ptr;
+ char *ptr, *saveptr = NULL;
int cnt = 1;
size_t len;
@@ -265,11 +266,11 @@ get_last_mount(void)
// mdata.dir: /home/netblue/.cache
// mdata.fstype: tmpfs
memset(&mdata, 0, sizeof(mdata));
- ptr = strtok(mbuf, " ");
+ ptr = potd_strtok(mbuf, " ", &saveptr);
if (!ptr)
goto errexit;
- while ((ptr = strtok(NULL, " ")) != NULL) {
+ while ((ptr = potd_strtok(NULL, " ", &saveptr)) != NULL) {
cnt++;
if (cnt == 4) {
mdata.fsname = ptr;
@@ -279,11 +280,11 @@ get_last_mount(void)
}
}
- ptr = strtok(NULL, "-");
+ ptr = potd_strtok(NULL, "-", &saveptr);
if (!ptr)
goto errexit;
- ptr = strtok(NULL, " ");
+ ptr = potd_strtok(NULL, " ", &saveptr);
if (!ptr)
goto errexit;
mdata.fstype = ptr++;
diff --git a/src/log.c b/src/log.c
index 240c12d..20e9444 100644
--- a/src/log.c
+++ b/src/log.c
@@ -35,6 +35,7 @@
#include <time.h>
#include "log.h"
+#include "compat.h"
log_priority log_prio = NOTICE;
log_open_cb log_open = NULL;
@@ -48,12 +49,12 @@ char *
curtime_str(char *buf, size_t siz)
{
time_t t;
- struct tm *tmp;
+ struct tm *tmp, res;
t = time(NULL);
- tmp = localtime(&t);
+ tmp = potd_localtime(&t, &res);
- if (!strftime(buf, siz, "%d %b %y - %H:%M:%S", tmp))
+ if (tmp && !strftime(buf, siz, "%d %b %y - %H:%M:%S", tmp))
snprintf(buf, siz, "%s", "UNKNOWN_TIME");
return buf;
diff --git a/src/main.c b/src/main.c
index 3816a77..9600176 100644
--- a/src/main.c
+++ b/src/main.c
@@ -371,8 +371,8 @@ int main(int argc, char *argv[])
N("%s (C) 2018 Toni Uhlig <%s>", PACKAGE_STRING, PACKAGE_BUGREPORT);
#endif
- ABORT_ON_FATAL( selftest_minimal_requirements(),
- "Selfcheck" );
+ if (selftest_minimal_requirements())
+ exit(EXIT_FAILURE);
if (geteuid() != 0) {
E("%s", "I was made for root!");
diff --git a/src/protocol_ssh.c b/src/protocol_ssh.c
index 9ad5110..7d6e935 100644
--- a/src/protocol_ssh.c
+++ b/src/protocol_ssh.c
@@ -57,6 +57,7 @@
#include "pseccomp.h"
#endif
#include "options.h"
+#include "compat.h"
#include "utils.h"
#include "log.h"
@@ -303,16 +304,16 @@ static int gen_default_keys(void)
char path[PATH_MAX];
char cmd[BUFSIZ];
int s = 0;
- struct passwd *pwd;
+ struct passwd pwd;
errno = 0;
- pwd = getpwnam(getopt_str(OPT_CHUSER));
+ if (potd_getpwnam(getopt_str(OPT_CHUSER), &pwd))
+ return 1;
+
if (mkdir(getopt_str(OPT_SSH_RUN_DIR), R_OK|W_OK|X_OK) && errno == ENOENT) {
if (chmod(getopt_str(OPT_SSH_RUN_DIR), S_IRWXU))
return 1;
- if (!pwd)
- return 1;
- if (chown(getopt_str(OPT_SSH_RUN_DIR), pwd->pw_uid, pwd->pw_gid))
+ if (chown(getopt_str(OPT_SSH_RUN_DIR), pwd.pw_uid, pwd.pw_gid))
return 1;
}
@@ -329,10 +330,8 @@ static int gen_default_keys(void)
}
if (chmod(path, S_IRUSR))
return 1;
- if (pwd) {
- if (chown(path, pwd->pw_uid, pwd->pw_gid))
- return 1;
- }
+ if (chown(path, pwd.pw_uid, pwd.pw_gid))
+ return 1;
snprintf(path, sizeof path, "%s/%s", getopt_str(OPT_SSH_RUN_DIR),
dsa_key_suf);
@@ -347,10 +346,8 @@ static int gen_default_keys(void)
}
if (chmod(path, S_IRUSR))
return 1;
- if (pwd) {
- if (chown(path, pwd->pw_uid, pwd->pw_gid))
- return 1;
- }
+ if (chown(path, pwd.pw_uid, pwd.pw_gid))
+ return 1;
snprintf(path, sizeof path, "%s/%s", getopt_str(OPT_SSH_RUN_DIR),
ecdsa_key_suf);
@@ -365,10 +362,8 @@ static int gen_default_keys(void)
}
if (chmod(path, S_IRUSR))
return 1;
- if (pwd) {
- if (chown(path, pwd->pw_uid, pwd->pw_gid))
- return 1;
- }
+ if (chown(path, pwd.pw_uid, pwd.pw_gid))
+ return 1;
return s != 0;
}
@@ -630,7 +625,7 @@ static int auth_password(const char *user, const char *pass,
size_t i;
double d;
time_t o, t = time(NULL);
- struct tm *tmp;
+ struct tm tmp;
char time_str[64] = {0};
for (i = 0; i < CACHE_MAX; ++i) {
@@ -644,8 +639,9 @@ static int auth_password(const char *user, const char *pass,
strncmp(pass, cache[i].pass, PASS_LEN) == 0 &&
strnlen(pass, PASS_LEN) == strnlen(cache[i].pass, PASS_LEN))
{
- tmp = localtime(&o);
- if (!strftime(time_str, sizeof time_str, "%H:%M:%S", tmp))
+ if (!potd_localtime(&o, &tmp))
+ continue;
+ if (!strftime(time_str, sizeof time_str, "%H:%M:%S", &tmp))
snprintf(time_str, sizeof time_str, "%s", "UNKNOWN_TIME");
N("Got cached user/pass '%s'/'%s' from %s",
user, pass, time_str);
diff --git a/src/utils.c b/src/utils.c
index 3cf88d5..edcfb31 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -63,6 +63,7 @@
#endif
#include "utils.h"
+#include "compat.h"
#ifdef HAVE_SECCOMP
#include "pseccomp.h"
#endif
@@ -379,8 +380,8 @@ int redirect_devnull_to(int fds, ...)
int change_user_group(const char *user, const char *group)
{
- struct passwd *pwd = NULL;
- struct group *grp = NULL;
+ struct passwd pwd;
+ struct group grp;
gid_t gid;
if (group)
@@ -388,22 +389,24 @@ int change_user_group(const char *user, const char *group)
else
D2("Change user to '%s' and its main group", user);
- pwd = getpwnam(user);
- if (!pwd)
+ if (potd_getpwnam(user, &pwd)) {
+ E_STRERR("Get uid from user '%s'", user);
return 1;
+ }
if (!group) {
- gid = pwd->pw_gid;
+ gid = pwd.pw_gid;
} else {
- grp = getgrnam(group);
- if (!grp)
+ if (potd_getgrnam(group, &grp)) {
+ E_STRERR("Get gid from group '%s'", group);
return 1;
- gid = grp->gr_gid;
+ }
+ gid = grp.gr_gid;
}
if (setresgid(gid, gid, gid))
return 1;
- if (setresuid(pwd->pw_uid, pwd->pw_uid, pwd->pw_uid))
+ if (setresuid(pwd.pw_uid, pwd.pw_uid, pwd.pw_uid))
return 1;
return 0;
@@ -1072,6 +1075,8 @@ int selftest_minimal_requirements(void)
goto error;
} else if (s >= 0) {
close(s);
+ if (chmod(getopt_str(OPT_ROFILE), S_IRUSR|S_IWUSR))
+ goto error;
}
if (mkdir(getopt_str(OPT_RODIR), S_IRWXU) && errno != EEXIST) {
E_STRERR("RO-directory '%s' check", getopt_str(OPT_RODIR));
@@ -1091,6 +1096,17 @@ int selftest_minimal_requirements(void)
goto error;
}
+ s = -1;
+ child_pid = fork();
+ if (!child_pid) {
+ if (change_default_user_group())
+ exit(EXIT_FAILURE);
+ else
+ exit(EXIT_SUCCESS);
+ } else waitpid(child_pid, &s, 0);
+ if (s)
+ goto error;
+
/* advanced sandbox tests */
if (getuid() == (uid_t) 0) {
child_pid = fork();
@@ -1103,16 +1119,16 @@ int selftest_minimal_requirements(void)
case 0:
if (clearenv()) {
E_STRERR("%s", "Clearing environment vairables");
- goto error;
+ exit(EXIT_FAILURE);
}
if (cgroups_set() || cgroups_activate()) {
E_STRERR("%s", "Activating cgroups");
- goto error;
+ exit(EXIT_FAILURE);
}
if (unshare(CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS))
{
E_STRERR("%s", "Unshare");
- goto error;
+ exit(EXIT_FAILURE);
}
mount_root();
#ifdef HAVE_SECCOMP
@@ -1120,10 +1136,12 @@ int selftest_minimal_requirements(void)
(getopt_used(OPT_SECCOMP_MINIMAL) ? PS_MINIMUM : 0));
if (pseccomp_default_rules(psc)) {
E_STRERR("%s", "Seccomp");
- goto error;
+ exit(EXIT_FAILURE);
}
pseccomp_free(&psc);
#endif
+
+ s = -1;
child_pid = fork();
if (!child_pid) {
if (safe_chroot(getopt_str(OPT_ROOT)))
@@ -1137,22 +1155,24 @@ int selftest_minimal_requirements(void)
#endif
exit(EXIT_SUCCESS);
} else waitpid(child_pid, &s, 0);
+
exit(s);
- break;
default:
waitpid(child_pid, &s, 0);
+ if (s)
+ goto error;
}
}
- if (getopt_used(OPT_RUNTEST)) {
- N("%s", "Selftest success");
+ N("%s", "Selftest success");
+ if (getopt_used(OPT_RUNTEST))
exit(EXIT_SUCCESS);
- }
+
return 0;
error:
- if (getopt_used(OPT_RUNTEST)) {
- E("%s", "Selftest failed");
+ E("%s", "Selftest failed");
+ if (getopt_used(OPT_RUNTEST))
exit(EXIT_FAILURE);
- }
+
return 1;
}