Implement user validation.

This commit is contained in:
Jordan Bancino 2022-08-10 11:58:39 -04:00
parent e0a66ad58a
commit 9ae05e84f2
5 changed files with 94 additions and 6 deletions

View file

@ -4,7 +4,7 @@
server-name "localhost";
chroot ".";
id "_telodendria" "_telodendria";
id "jordan";
data-dir "./data";
federation "true";
registration "true";

View file

@ -227,8 +227,10 @@ you on a sufficiently complete operating system:
</p>
<ul>
<li>
A standards-compliant C compiler with a POSIX.1c standard library. Because
<b>Telodendria</b> is written in ANSI C and sticks to POSIX.1c features, it
A standards-compliant C compiler with a POSIX.1c standard library and
access to a <code>chroot()</code> system call (which is available in all
UNIX-like operating systems, but is not POSIX.) Because <b>Telodendria</b>
is written in ANSI C and sticks almost entirely to POSIX.1c features, it
should compile on almost any compiler and operating system with minimal
effort, but the following compilers and operating systems are known to work:
<ul>

View file

@ -26,6 +26,9 @@
#include <string.h>
#include <unistd.h>
#include <grp.h>
#include <pwd.h>
#include <TelodendriaConfig.h>
#include <Log.h>
@ -88,6 +91,10 @@ main(int argc, char **argv)
/* Program configuration */
TelodendriaConfig *tConfig = NULL;
/* User validation */
struct passwd *userInfo;
struct group *groupInfo;
lc = LogConfigCreate();
if (!lc)
@ -185,6 +192,71 @@ main(int argc, char **argv)
Log(lc, LOG_DEBUG, "Flags: %x", tConfig->flags);
LogConfigUnindent(lc);
Log(lc, LOG_TASK, "Evaluating permissions...");
if (chdir(tConfig->chroot) != 0)
{
Log(lc, LOG_ERROR, "Unable to change into directory: %s.", tConfig->chroot);
exit = EXIT_FAILURE;
goto finish;
}
Log(lc, LOG_DEBUG, "Running as uid/gid: %d/%d.", getuid(), getgid());
userInfo = getpwnam(tConfig->uid);
groupInfo = getgrnam(tConfig->gid);
if (!userInfo || !groupInfo)
{
Log(lc, LOG_ERROR, "Unable to locate the user/group specified in the configuration.");
exit = EXIT_FAILURE;
goto finish;
}
if (getuid() == 0)
{
if (chroot(tConfig->chroot) == 0)
{
Log(lc, LOG_MESSAGE, "Changed the root directory to: %s.", tConfig->chroot);
}
else
{
Log(lc, LOG_WARNING, "Unable to chroot into directory: %s.", tConfig->chroot);
}
if (setgid(groupInfo->gr_gid) != 0 || setuid(userInfo->pw_uid) != 0)
{
Log(lc, LOG_WARNING, "Unable to set process uid/gid.");
}
else
{
Log(lc, LOG_MESSAGE, "Set uid/gid to %s:%s.", tConfig->uid, tConfig->gid);
}
}
else
{
Log(lc, LOG_MESSAGE, "Not changing root directory, because we are not root.");
if (getuid() != userInfo->pw_uid || getgid() != groupInfo->gr_gid)
{
Log(lc, LOG_WARNING, "Not running as the uid/gid specified in the configuration.");
}
else
{
Log(lc, LOG_DEBUG, "Running as the uid/gid specified in the configuration.");
}
}
/* These config values are no longer needed; don't hold them in
* memory anymore */
free(tConfig->chroot);
free(tConfig->uid);
free(tConfig->gid);
tConfig->chroot = NULL;
tConfig->uid = NULL;
tConfig->gid = NULL;
finish:
Log(lc, LOG_DEBUG, "Exiting with code '%d'.", exit);
TelodendriaConfigFree(tConfig);

View file

@ -119,9 +119,23 @@ TelodendriaConfigParse(HashMap * config, LogConfig * lc)
GET_DIRECTIVE("id");
ASSERT_NO_CHILDREN("id");
ASSERT_VALUES("id", 2);
COPY_VALUE(tConfig->uid, 0);
switch (ArraySize(value))
{
case 1:
Log(lc, LOG_WARNING, "No run group specified; assuming it's the same as the user.");
tConfig->gid = UtilStringDuplicate(tConfig->uid);
break;
case 2:
COPY_VALUE(tConfig->gid, 1);
break;
default:
Log(lc, LOG_ERROR,
"Wrong value count in directive 'id': got '%d', but expected 1 or 2.",
ArraySize(value));
break;
}
GET_DIRECTIVE("data-dir");
ASSERT_NO_CHILDREN("data-dir");

View file

@ -22,7 +22,7 @@
: "${TELODENDRIA_VERSION:=0.0.0}"
: "${CVS_TAG:=Telodendria-$(echo $TELODENDRIA_VERSION | sed 's/\./_/g')}"
: "${DEFINES:=-D_POSIX_C_SOURCE=199506L -DTELODENDRIA_VERSION=\"$TELODENDRIA_VERSION\"}"
: "${DEFINES:=-D_BSD_SOURCE -D_POSIX_C_SOURCE=199506L -DTELODENDRIA_VERSION=\"$TELODENDRIA_VERSION\"}"
: "${INCLUDES:=-Isrc/include}"
: "${CC:=cc}"