From 1049632873d5a70cda90e5c4ed87312bfe4810d6 Mon Sep 17 00:00:00 2001 From: David Steele Date: Sun, 8 Sep 2019 20:11:51 -0400 Subject: [PATCH] Add user module for managing system users/groups. Centralize the management of users and groups. Also update Posix storage driver where users/groups were already in use. --- libc/Makefile.PL | 1 + src/Makefile.in | 6 +- src/common/user.c | 136 ++++++++++++++++++++++++++++++ src/common/user.h | 36 ++++++++ src/storage/posix/storage.c | 20 ++--- test/define.yaml | 7 ++ test/src/module/common/userTest.c | 30 +++++++ 7 files changed, 221 insertions(+), 15 deletions(-) create mode 100644 src/common/user.c create mode 100644 src/common/user.h create mode 100644 test/src/module/common/userTest.c diff --git a/libc/Makefile.PL b/libc/Makefile.PL index 1c8dc5919..197e8478e 100644 --- a/libc/Makefile.PL +++ b/libc/Makefile.PL @@ -87,6 +87,7 @@ my @stryCFile = 'common/type/variant.c', 'common/type/variantList.c', 'common/type/xml.c', + 'common/user.c', 'common/wait.c', 'config/config.c', 'config/define.c', diff --git a/src/Makefile.in b/src/Makefile.in index 358030660..adf93de9d 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -122,6 +122,7 @@ SRCS = \ common/type/variant.c \ common/type/variantList.c \ common/type/xml.c \ + common/user.c \ common/wait.c \ config/config.c \ config/define.c \ @@ -443,6 +444,9 @@ common/type/variantList.o: common/type/variantList.c build.auto.h common/assert. common/type/xml.o: common/type/xml.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/list.h common/type/string.h common/type/xml.h $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c common/type/xml.c -o common/type/xml.o +common/user.o: common/user.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/logLevel.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/string.h common/user.h + $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c common/user.c -o common/user.o + common/wait.o: common/wait.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/stackTrace.h common/time.h common/type/convert.h common/wait.h $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c common/wait.c -o common/wait.o @@ -563,7 +567,7 @@ storage/helper.o: storage/helper.c build.auto.h common/assert.h common/debug.h c storage/posix/read.o: storage/posix/read.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/read.intern.h common/io/write.h common/io/write.intern.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h storage/info.h storage/posix/read.h storage/posix/storage.h storage/posix/storage.intern.h storage/read.h storage/read.intern.h storage/storage.h storage/storage.intern.h storage/write.h storage/write.intern.h version.h $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c storage/posix/read.c -o storage/posix/read.o -storage/posix/storage.o: storage/posix/storage.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/read.intern.h common/io/write.h common/io/write.intern.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/regExp.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h storage/info.h storage/posix/read.h storage/posix/storage.h storage/posix/storage.intern.h storage/posix/write.h storage/read.h storage/read.intern.h storage/storage.h storage/storage.intern.h storage/write.h storage/write.intern.h version.h +storage/posix/storage.o: storage/posix/storage.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/read.intern.h common/io/write.h common/io/write.intern.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/regExp.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h common/user.h storage/info.h storage/posix/read.h storage/posix/storage.h storage/posix/storage.intern.h storage/posix/write.h storage/read.h storage/read.intern.h storage/storage.h storage/storage.intern.h storage/write.h storage/write.intern.h version.h $(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c storage/posix/storage.c -o storage/posix/storage.o storage/posix/write.o: storage/posix/write.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/read.intern.h common/io/write.h common/io/write.intern.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h storage/info.h storage/posix/storage.h storage/posix/storage.intern.h storage/posix/write.h storage/read.h storage/read.intern.h storage/storage.h storage/storage.intern.h storage/write.h storage/write.intern.h version.h diff --git a/src/common/user.c b/src/common/user.c new file mode 100644 index 000000000..8e02cb880 --- /dev/null +++ b/src/common/user.c @@ -0,0 +1,136 @@ +/*********************************************************************************************************************************** +System User/Group Management +***********************************************************************************************************************************/ +#include "build.auto.h" + +#include +#include +#include + +#include "common/debug.h" +#include "common/memContext.h" +#include "common/user.h" + +/*********************************************************************************************************************************** +User group info +***********************************************************************************************************************************/ +struct +{ + MemContext *memContext; // Mem context to store data in this struct + + uid_t userId; // Real user id of the calling process from getuid() + bool userRoot; // Is this the root user? + const String *userName; // User name if it exists + + gid_t groupId; // Real group id of the calling process from getgid() + const String *groupName; // Group name if it exists +} userLocalData; + +/***********************************************************************************************************************************/ +static void +userInitInternal(void) +{ + FUNCTION_TEST_VOID(); + + MEM_CONTEXT_BEGIN(memContextTop()) + { + userLocalData.memContext = memContextNew("UserLocalData"); + } + MEM_CONTEXT_END(); + + MEM_CONTEXT_BEGIN(userLocalData.memContext) + { + userLocalData.userId = getuid(); + userLocalData.userName = userNameFromId(userLocalData.userId); + userLocalData.userRoot = userLocalData.userId == 0; + + userLocalData.groupId = getgid(); + userLocalData.groupName = groupNameFromId(userLocalData.groupId); + } + MEM_CONTEXT_END(); + + FUNCTION_TEST_RETURN_VOID(); +} + +void +userInit(void) +{ + FUNCTION_TEST_VOID(); + + if (!userLocalData.memContext) + userInitInternal(); + + FUNCTION_TEST_RETURN_VOID(); +} + +/**********************************************************************************************************************************/ +gid_t +groupId(void) +{ + FUNCTION_TEST_VOID(); + FUNCTION_TEST_RETURN(userLocalData.groupId); +} + +/**********************************************************************************************************************************/ +const String * +groupName(void) +{ + FUNCTION_TEST_VOID(); + FUNCTION_TEST_RETURN(userLocalData.groupName); +} + +/**********************************************************************************************************************************/ +String * +groupNameFromId(gid_t groupId) +{ + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(UINT, groupId); + FUNCTION_TEST_END(); + + struct group *groupData = getgrgid(groupId); + + if (groupData != NULL) + FUNCTION_TEST_RETURN(strNew(groupData->gr_name)); + + FUNCTION_TEST_RETURN(NULL); +} + +/**********************************************************************************************************************************/ +uid_t +userId(void) +{ + FUNCTION_TEST_VOID(); + FUNCTION_TEST_RETURN(userLocalData.userId); +} + +/**********************************************************************************************************************************/ +const String * +userName(void) +{ + FUNCTION_TEST_VOID(); + FUNCTION_TEST_RETURN(userLocalData.userName); +} + +/**********************************************************************************************************************************/ +String * +userNameFromId(uid_t userId) +{ + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(UINT, userId); + FUNCTION_TEST_END(); + + struct passwd *userData = getpwuid(userId); + + if (userData != NULL) + FUNCTION_TEST_RETURN(strNew(userData->pw_name)); + + FUNCTION_TEST_RETURN(NULL); +} + +/**********************************************************************************************************************************/ +bool +userRoot(void) +{ + FUNCTION_TEST_VOID(); + FUNCTION_TEST_RETURN(userLocalData.userRoot); +} diff --git a/src/common/user.h b/src/common/user.h new file mode 100644 index 000000000..0c371f2e0 --- /dev/null +++ b/src/common/user.h @@ -0,0 +1,36 @@ +/*********************************************************************************************************************************** +System User/Group Management +***********************************************************************************************************************************/ +#ifndef COMMON_USER_H +#define COMMON_USER_H + +#include "common/type/string.h" + +/*********************************************************************************************************************************** +Functions +***********************************************************************************************************************************/ +// Call this initializer before using any of the functions below. Safe to call more than once. +void userInit(void); + +// Get the primary group id of the current user +gid_t groupId(void); + +// Get the primary group name of the current user. Returns NULL if there is no mapping. +const String *groupName(void); + +// Get the group name from a group id. Returns NULL if the group id is invalid or there is no mapping. +String *groupNameFromId(gid_t groupId); + +// Get the id of the current user +uid_t userId(void); + +// Get the name of the current user. Returns NULL if there is no mapping. +const String *userName(void); + +// Get the user name from a user id. Returns NULL if the user id is invalid or there is no mapping. +String *userNameFromId(uid_t userId); + +// Is the current user the root user? +bool userRoot(void); + +#endif diff --git a/src/storage/posix/storage.c b/src/storage/posix/storage.c index bd4986349..cc1243d66 100644 --- a/src/storage/posix/storage.c +++ b/src/storage/posix/storage.c @@ -6,9 +6,7 @@ Posix Storage #include #include #include -#include #include -#include #include #include #include @@ -18,6 +16,7 @@ Posix Storage #include "common/log.h" #include "common/memContext.h" #include "common/regExp.h" +#include "common/user.h" #include "storage/posix/read.h" #include "storage/posix/storage.intern.h" #include "storage/posix/write.h" @@ -109,21 +108,11 @@ storagePosixInfo(THIS_VOID, const String *file, bool followLink) { result.exists = true; result.groupId = statFile.st_gid; + result.group = groupNameFromId(result.groupId); result.userId = statFile.st_uid; + result.user = userNameFromId(result.userId); result.timeModified = statFile.st_mtime; - // Get user name if it exists - struct passwd *userData = getpwuid(result.userId); - - if (userData != NULL) - result.user = strNew(userData->pw_name); - - // Get group name if it exists - struct group *groupData = getgrgid(result.groupId); - - if (groupData != NULL) - result.group = strNew(groupData->gr_name); - if (S_ISREG(statFile.st_mode)) { result.type = storageTypeFile; @@ -679,6 +668,9 @@ storagePosixNewInternal( ASSERT(modeFile != 0); ASSERT(modePath != 0); + // Initialze user module + userInit(); + // Create the object Storage *this = NULL; diff --git a/test/define.yaml b/test/define.yaml index 595e01263..639c50b71 100644 --- a/test/define.yaml +++ b/test/define.yaml @@ -213,6 +213,13 @@ unit: coverage: common/type/xml: full + # ---------------------------------------------------------------------------------------------------------------------------- + - name: user + total: 1 + + coverage: + common/user: full + # ---------------------------------------------------------------------------------------------------------------------------- - name: io total: 4 diff --git a/test/src/module/common/userTest.c b/test/src/module/common/userTest.c new file mode 100644 index 000000000..d13dfd38b --- /dev/null +++ b/test/src/module/common/userTest.c @@ -0,0 +1,30 @@ +/*********************************************************************************************************************************** +Test System User/Group Management +***********************************************************************************************************************************/ + +/*********************************************************************************************************************************** +Test Run +***********************************************************************************************************************************/ +void +testRun(void) +{ + FUNCTION_HARNESS_VOID(); + + // ***************************************************************************************************************************** + if (testBegin("all")) + { + TEST_RESULT_VOID(userInit(), "initialize info"); + TEST_RESULT_VOID(userInit(), "initialize info again"); + + TEST_RESULT_UINT(userId(), getuid(), "check user id"); + TEST_RESULT_STR_Z(userName(), testUser(), "check user name"); + TEST_RESULT_STR_Z(userNameFromId(77777), NULL, "invalid user name by id"); + TEST_RESULT_BOOL(userRoot(), false, "check user is root"); + + TEST_RESULT_UINT(groupId(), getgid(), "check group id"); + TEST_RESULT_STR_Z(groupName(), testGroup(), "check name name"); + TEST_RESULT_STR_Z(groupNameFromId(77777), NULL, "invalid group name by id"); + } + + FUNCTION_HARNESS_RESULT_VOID(); +}