From f694f63e2bb877820914fddd71dbdc71884f33f6 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 19 Apr 2008 00:10:51 +0000 Subject: [PATCH] * Moved private passwd/group/shadow passwd limit constants from to . * Added support in the registrar for adding and modifying users. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25040 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/libroot/libroot_private.h | 32 --- headers/private/libroot/user_group.h | 37 +++ .../registrar/AuthenticationManager.cpp | 226 +++++++++++++++++- src/system/libroot/os/find_directory.c | 2 +- src/system/libroot/posix/unistd/conf.c | 1 + 5 files changed, 262 insertions(+), 36 deletions(-) diff --git a/headers/private/libroot/libroot_private.h b/headers/private/libroot/libroot_private.h index 2f6c95d931..772b698288 100644 --- a/headers/private/libroot/libroot_private.h +++ b/headers/private/libroot/libroot_private.h @@ -10,38 +10,6 @@ #include -#define MAX_PASSWD_NAME_LEN (32) -#define MAX_PASSWD_PASSWORD_LEN (32) -#define MAX_PASSWD_REAL_NAME_LEN (128) -#define MAX_PASSWD_HOME_DIR_LEN (B_PATH_NAME_LENGTH) -#define MAX_PASSWD_SHELL_LEN (B_PATH_NAME_LENGTH) - -#define MAX_PASSWD_BUFFER_SIZE ( \ - MAX_PASSWD_NAME_LEN \ - + MAX_PASSWD_PASSWORD_LEN \ - + MAX_PASSWD_REAL_NAME_LEN \ - + MAX_PASSWD_HOME_DIR_LEN \ - + MAX_PASSWD_SHELL_LEN) - -#define MAX_GROUP_NAME_LEN (32) -#define MAX_GROUP_PASSWORD_LEN (32) -#define MAX_GROUP_MEMBER_COUNT (32) - -#define MAX_GROUP_BUFFER_SIZE ( \ - MAX_GROUP_NAME_LEN \ - + MAX_GROUP_PASSWORD_LEN \ - + ((MAX_GROUP_MEMBER_COUNT + 1) * sizeof(char*))) - // MAX_GROUP_NAME_LEN and MAX_GROUP_PASSWORD_LEN are char* aligned - - -#define MAX_SHADOW_PWD_NAME_LEN (32) -#define MAX_SHADOW_PWD_PASSWORD_LEN (128) - -#define MAX_SHADOW_PWD_BUFFER_SIZE ( \ - MAX_SHADOW_PWD_NAME_LEN \ - + MAX_SHADOW_PWD_PASSWORD_LEN) - - struct user_space_program_args; struct real_time_data; diff --git a/headers/private/libroot/user_group.h b/headers/private/libroot/user_group.h index 7aba8200b1..858dbd6ad6 100644 --- a/headers/private/libroot/user_group.h +++ b/headers/private/libroot/user_group.h @@ -11,6 +11,41 @@ #include + +#define MAX_PASSWD_NAME_LEN (32) +#define MAX_PASSWD_PASSWORD_LEN (32) +#define MAX_PASSWD_REAL_NAME_LEN (128) +#define MAX_PASSWD_HOME_DIR_LEN (B_PATH_NAME_LENGTH) +#define MAX_PASSWD_SHELL_LEN (B_PATH_NAME_LENGTH) + +#define MAX_PASSWD_BUFFER_SIZE ( \ + MAX_PASSWD_NAME_LEN \ + + MAX_PASSWD_PASSWORD_LEN \ + + MAX_PASSWD_REAL_NAME_LEN \ + + MAX_PASSWD_HOME_DIR_LEN \ + + MAX_PASSWD_SHELL_LEN) + +#define MAX_GROUP_NAME_LEN (32) +#define MAX_GROUP_PASSWORD_LEN (32) +#define MAX_GROUP_MEMBER_COUNT (32) + +#define MAX_GROUP_BUFFER_SIZE ( \ + MAX_GROUP_NAME_LEN \ + + MAX_GROUP_PASSWORD_LEN \ + + ((MAX_GROUP_MEMBER_COUNT + 1) * sizeof(char*))) + // MAX_GROUP_NAME_LEN and MAX_GROUP_PASSWORD_LEN are char* aligned + + +#define MAX_SHADOW_PWD_NAME_LEN (32) +#define MAX_SHADOW_PWD_PASSWORD_LEN (128) + +#define MAX_SHADOW_PWD_BUFFER_SIZE ( \ + MAX_SHADOW_PWD_NAME_LEN \ + + MAX_SHADOW_PWD_PASSWORD_LEN) + + +#ifdef __cplusplus + #include @@ -106,4 +141,6 @@ status_t parse_shadow_pwd_line(char* line, char*& name, char*& password, } // namespace BPrivate +#endif // __cplusplus + #endif // _LIBROOT_USER_GROUP_COMMON_H diff --git a/src/servers/registrar/AuthenticationManager.cpp b/src/servers/registrar/AuthenticationManager.cpp index e34eb6bd15..0726eb62ae 100644 --- a/src/servers/registrar/AuthenticationManager.cpp +++ b/src/servers/registrar/AuthenticationManager.cpp @@ -103,6 +103,20 @@ private: class AuthenticationManager::User { public: + User() + : + fUID(0), + fGID(0), + fLastChanged(0), + fMin(-1), + fMax(-1), + fWarn(-1), + fInactive(-1), + fExpiration(-1), + fFlags(0) + { + } + User(const char* name, const char* password, uid_t uid, gid_t gid, const char* home, const char* shell, const char* realName) : @@ -123,6 +137,26 @@ public: { } + User(const User& other) + : + fUID(other.fUID), + fGID(other.fGID), + fName(other.fName), + fPassword(other.fPassword), + fHome(other.fHome), + fShell(other.fShell), + fRealName(other.fRealName), + fShadowPassword(other.fShadowPassword), + fLastChanged(other.fLastChanged), + fMin(other.fMin), + fMax(other.fMax), + fWarn(other.fWarn), + fInactive(other.fInactive), + fExpiration(other.fExpiration), + fFlags(other.fFlags) + { + } + const string& Name() const { return fName; } const uid_t UID() const { return fUID; } @@ -139,6 +173,56 @@ public: fFlags = flags; } + void UpdateFromMessage(const KMessage& message) + { + int32 intValue; + const char* stringValue; + + if (message.FindInt32("uid", &intValue) == B_OK) + fUID = intValue; + + if (message.FindInt32("gid", &intValue) == B_OK) + fGID = intValue; + + if (message.FindString("name", &stringValue) == B_OK) + fName = stringValue; + + if (message.FindString("password", &stringValue) == B_OK) + fPassword = stringValue; + + if (message.FindString("home", &stringValue) == B_OK) + fHome = stringValue; + + if (message.FindString("shell", &stringValue) == B_OK) + fShell = stringValue; + + if (message.FindString("real name", &stringValue) == B_OK) + fRealName = stringValue; + + if (message.FindString("shadow password", &stringValue) == B_OK) { + fShadowPassword = stringValue; + // TODO: + // fLastChanged = now; + } + + if (message.FindInt32("min", &intValue) == B_OK) + fMin = intValue; + + if (message.FindInt32("max", &intValue) == B_OK) + fMax = intValue; + + if (message.FindInt32("warn", &intValue) == B_OK) + fWarn = intValue; + + if (message.FindInt32("inactive", &intValue) == B_OK) + fInactive = intValue; + + if (message.FindInt32("expiration", &intValue) == B_OK) + fExpiration = intValue; + + if (message.FindInt32("flags", &intValue) == B_OK) + fFlags = intValue; + } passwd* WriteFlatPasswd(FlatStore& store) const { @@ -204,6 +288,30 @@ public: return B_OK; } + void WritePasswdLine(FILE* file) + { + fprintf(file, "%s:%s:%d:%d:%s:%s:%s\n", + fName.c_str(), fPassword.c_str(), (int)fUID, (int)fGID, + fRealName.c_str(), fHome.c_str(), fShell.c_str()); + } + + void WriteShadowPwdLine(FILE* file) + { + fprintf(file, "%s:%s:%d:", fName.c_str(), fShadowPassword.c_str(), + fLastChanged); + + // The following values are supposed to be printed as empty strings, + // if negative. + int values[5] = { fMin, fMax, fWarn, fInactive, fExpiration }; + for (int i = 0; i < 5; i++) { + if (values[i] >= 0) + fprintf(file, "%d", values[i]); + fprintf(file, ":"); + } + + fprintf(file, "%d\n", fFlags); + } + private: uid_t fUID; gid_t fGID; @@ -375,6 +483,42 @@ public: return count; } + void WriteToDisk() + { + // rename the old files + string passwdBackup(kPasswdFile); + string shadowBackup(kShadowPwdFile); + passwdBackup += ".old"; + shadowBackup += ".old"; + + rename(kPasswdFile, passwdBackup.c_str()); + rename(kShadowPwdFile, shadowBackup.c_str()); + // Don't check errors. We can't do anything anyway. + + // open files + FILE* passwdFile = fopen(kPasswdFile, "w"); + if (passwdFile == NULL) { + debug_printf("REG: Failed to open passwd file \"%s\" for " + "writing: %s\n", kPasswdFile, strerror(errno)); + } + CObjectDeleter _1(passwdFile, fclose); + + FILE* shadowFile = fopen(kShadowPwdFile, "w"); + if (shadowFile == NULL) { + debug_printf("REG: Failed to open shadow passwd file \"%s\" for " + "writing: %s\n", kShadowPwdFile, strerror(errno)); + } + CObjectDeleter _2(shadowFile, fclose); + + // write users + for (map::const_iterator it = fUsersByID.begin(); + it != fUsersByID.end(); ++it) { + User* user = it->second; + user->WritePasswdLine(passwdFile); + user->WriteShadowPwdLine(shadowFile); + } + } + private: map fUsersByID; map fUsersByName; @@ -547,6 +691,8 @@ AuthenticationManager::_RequestThread() if (error != B_OK) return B_OK; + bool isRoot = (messageInfo.sender == 0); + switch (message.What()) { case B_REG_GET_PASSWD_DB: { @@ -614,7 +760,7 @@ AuthenticationManager::_RequestThread() case B_REG_GET_SHADOW_PASSWD_DB: { // only root may see the shadow passwd - if (messageInfo.sender != 0) + if (!isRoot) error = EPERM; // lazily build the reply @@ -668,7 +814,7 @@ AuthenticationManager::_RequestThread() bool getShadowPwd = message.GetBool("shadow", false); // only root may see the shadow passwd - if (error == B_OK && getShadowPwd && messageInfo.sender != 0) + if (error == B_OK && getShadowPwd && !isRoot) error = EPERM; // add user to message @@ -751,8 +897,82 @@ AuthenticationManager::_RequestThread() } case B_REG_UPDATE_USER: - case B_REG_UPDATE_GROUP: + { + // find user + User* user = NULL; + int32 uid; + const char* name; + + if (message.FindInt32("uid", &uid) == B_OK) { + user = fUserDB->UserByID(uid); + } else if (message.FindString("name", &name) == B_OK) { + user = fUserDB->UserByName(name); + } else { + error = B_BAD_VALUE; + } + + // only can change anything + if (error == B_OK && !isRoot) + error = EPERM; + + // check addUser vs. existing user + bool addUser = message.GetBool("add user", false); + if (error == B_OK) { + if (addUser) { + if (user != NULL) + error = EEXIST; + } else if (user == NULL) + error = ENOENT; + } + + // apply all changes + if (error == B_OK) { + // clone the user object and update it from the message + User* oldUser = user; + user = NULL; + try { + user = (oldUser != NULL ? new User(*oldUser) + : new User); + user->UpdateFromMessage(message); + + // uid and name should remain the same + if (oldUser != NULL) { + if (oldUser->UID() != user->UID() + || oldUser->Name() != user->Name()) { + error = B_BAD_VALUE; + } + } + + // replace the old user and write DBs to disk + if (error == B_OK) { + fUserDB->AddUser(user); + fUserDB->WriteToDisk(); + fPasswdDBReply->SetTo(1); + fShadowPwdDBReply->SetTo(1); + } + } catch (...) { + error = B_NO_MEMORY; + } + + if (error == B_OK) + delete oldUser; + else + delete user; + } + + // send reply + KMessage reply; + reply.SetWhat(error); + message.SendReply(&reply, -1, -1, 0, registrarTeam); + break; + } + case B_REG_UPDATE_GROUP: + debug_printf("B_REG_UPDATE_GROUP done: currently unsupported!\n"); + break; + default: + debug_printf("REG: invalid message: %lu\n", message.What()); + } } } diff --git a/src/system/libroot/os/find_directory.c b/src/system/libroot/os/find_directory.c index def3a55f72..f91808cdd0 100644 --- a/src/system/libroot/os/find_directory.c +++ b/src/system/libroot/os/find_directory.c @@ -22,7 +22,7 @@ #include #include -#include +#include /* use pwents to find home */ #define USE_PWENTS diff --git a/src/system/libroot/posix/unistd/conf.c b/src/system/libroot/posix/unistd/conf.c index 4f95e181a2..a64563efe4 100644 --- a/src/system/libroot/posix/unistd/conf.c +++ b/src/system/libroot/posix/unistd/conf.c @@ -15,6 +15,7 @@ #include #include +#include int