int RepairRootGroup()

in src/common/commonutils/UserUtils.c [1170:1271]


int RepairRootGroup(OsConfigLogHandle log)
{
    const char* etcGroup = "/etc/group";
    const char* rootLine = "root:x:0:\n";
    const char* tempFileName = "/etc/~group";
    SimplifiedGroup* groupList = NULL;
    unsigned int groupListSize = 0;
    unsigned int i = 0;
    bool found = false;
    char* original = NULL;
    int status = 0;

    if (0 == (status = EnumerateAllGroups(&groupList, &groupListSize, NULL, log)))
    {
        for (i = 0; i < groupListSize; i++)
        {
            if ((0 == strcmp(groupList[i].groupName, g_root)) && (0 == groupList[i].groupId))
            {
                OsConfigLogInfo(log, "CheckRootGroupExists: root group exists with gid 0");
                found = true;
                break;
            }
        }
    }

    FreeGroupList(&groupList, groupListSize);

    if (false == found)
    {
        // Load content of /etc/group
        if (NULL != (original = LoadStringFromFile(etcGroup, false, log)))
        {
            // Save content loaded from /etc/group to temporary file
            if (SavePayloadToFile(tempFileName, rootLine, strlen(rootLine), log))
            {
                // Delete from temporary file any lines containing "root"
                if (0 == (status = ReplaceMarkedLinesInFile(tempFileName, g_root, NULL, '#', false, log)))
                {
                    // Free the previously loaded content, we'll reload
                    FREE_MEMORY(original);

                    // Load the fixed content of temporary file
                    if (NULL != (original = LoadStringFromFile(tempFileName, false, log)))
                    {
                        // Delete the previously created temporary file, we'll recreate
                        remove(tempFileName);

                        // Save correct root line to the recreated temporary file
                        if (SavePayloadToFile(tempFileName, rootLine, strlen(rootLine), log))
                        {
                            // Append to temporary file the cleaned content
                            if (AppendPayloadToFile(tempFileName, original, strlen(original), log))
                            {
                                // In a single atomic operation move edited contents from temporary file to /etc/group
                                if (0 != (status = RenameFileWithOwnerAndAccess(tempFileName, etcGroup, log)))
                                {
                                    OsConfigLogInfo(log, "RepairRootGroup:  RenameFileWithOwnerAndAccess('%s' to '%s') returned %d",
                                        tempFileName, etcGroup, status);
                                }
                            }
                            else
                            {
                                OsConfigLogInfo(log, "RepairRootGroup: cannot append to to temp file '%s' (%d)", tempFileName, errno);
                                status = ENOENT;
                            }

                            remove(tempFileName);
                        }
                    }
                    else
                    {
                        OsConfigLogInfo(log, "RepairRootGroup: cannot read from '%s' (%d)", tempFileName, errno);
                        status = EACCES;
                    }
                }
                else
                {
                    OsConfigLogInfo(log, "RepairRootGroup: cannot remove potentially corrupted root entries from '%s' (%d)", etcGroup, errno);
                }
            }
            else
            {
                OsConfigLogInfo(log, "RepairRootGroup: cannot save to temp file '%s' (%d)", tempFileName, errno);
                status = EPERM;
            }

            FREE_MEMORY(original);
        }
        else
        {
            OsConfigLogInfo(log, "RepairRootGroup: cannot read from '%s' (%d)", etcGroup, errno);
            status = EACCES;
        }
    }

    if (0 == status)
    {
        OsConfigLogInfo(log, "RepairRootGroup: root group exists with gid 0");
    }

    return status;
}