added: now we have a fourth part in permissions (guests)

e.g.: 07555 means:
           7 for owner
           5 for group
           5 for others
           5 for guests (not logged users)
added:     the sticky bit for directories
           e.g. permissions to a directory with a sticky bit set
           can be set to: 017555
rewritten: rm/mv winix functions to correctly understand the sticky bit
added:     Dir::FollowLink() recognizes ".." and "." now
           consequently System::FollowAllLinks recognizes it too
added:     umask -- calculating privileges for new files/directories
           all users have their own umask (in meta)
           and there is one in the config
           (for guests and when a user has not definied its own one)
removed:   mount option: only_root_remove



git-svn-id: svn://ttmath.org/publicrep/winix/trunk@801 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
2012-01-24 23:03:36 +00:00
parent 5aaab89cd8
commit 6e2d00bc5b
34 changed files with 1109 additions and 557 deletions

View File

@@ -229,6 +229,7 @@ void Config::AssignValues(bool stdout_is_closed)
pattern_cacher_how_many_delete = Size(L"pattern_cacher_how_many_delete", 30);
content_type_header = Int(L"content_type_header", 0);
umask = Int(L"umask", 0222);
}

View File

@@ -453,7 +453,10 @@ public:
// if utf8 is true then "; charset=UTF-8" will also be appended
int content_type_header;
// global umask
// it is used when an user doesn't have your own umask or for guests (not logged users)
// default: 0222
int umask;

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2008-2010, Tomasz Sowa
* Copyright (c) 2008-2012, Tomasz Sowa
* All rights reserved.
*
*/
@@ -48,7 +48,7 @@ public:
bool DelById(long id);
ParentIterator ParentBegin();
ParentIterator ParentBegin(); // IMPROVE ME: may it should be renamed to ChildBegin() similarly as FindFirstChild() ?
ParentIterator ParentEnd();
ParentSizeType ParentSize();
bool ParentEmpty();

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2008-2011, Tomasz Sowa
* Copyright (c) 2008-2012, Tomasz Sowa
* All rights reserved.
*
*/
@@ -41,7 +41,7 @@ void Dirs::Clear()
bool Dirs::HasReadExecAccessForRoot(const Item & item)
{
// there must be at least one 'x' (for the root)
return (item.privileges & 01111) != 0; // !! in the future there'll be another 'x'
return (item.privileges & 01111) != 0;
}
@@ -53,8 +53,8 @@ void Dirs::CheckRootDir()
{
if( !HasReadExecAccessForRoot(*i) )
{
i->privileges = 0755;
log << log1 << "Dirs: there is no access for root (admin) to the root dir, setting 0755 for root dir" << logend;
i->privileges = 07555;
log << log1 << "Dirs: there is no access for a root (admin) to the root dir, setting 07555 for the root directory" << logend;
db->EditPrivById(*i, i->id);
}
@@ -62,7 +62,7 @@ void Dirs::CheckRootDir()
}
log << log1 << "Dirs: there is no a root dir in the database (creating one)" << logend;
log << log1 << "Dirs: there is no a root directory in the database (creating one)" << logend;
Item root;
@@ -70,7 +70,7 @@ void Dirs::CheckRootDir()
root.parent_id = -1;
root.user_id = -1;
root.group_id = -1;
root.privileges = 0755;
root.privileges = 07555;
// !! upewnic sie ze baza nie zmieni url (gdyby wczesniej juz byl w bazie pusty url)
// !! zrobic jakis wyjatek do wprowadzania roota?
@@ -487,7 +487,7 @@ return 0;
// current_dir_tab can be the same container as out_dir_tab
// current_dir_tab can be the same container as out_dir_tab
void Dirs::CopyDirTab(const std::vector<Item*> & in, std::vector<Item*> & out)
{
if( &in != &out )
@@ -502,13 +502,13 @@ void Dirs::CopyDirTab(const std::vector<Item*> & in, std::vector<Item*> & out)
size_t Dirs::AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_to)
bool Dirs::AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_to, size_t & i)
{
if( dir_tab.empty() )
return 0;
size_t i = 0;
size_t old_i;
i = 0;
if( dir_tab.empty() )
return false;
while( true )
{
@@ -516,7 +516,7 @@ size_t Dirs::AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_
for( ; i<link_to.size() && link_to[i] == '/' ; ++i);
if( i == link_to.size() )
return i; // end of the path
return true; // end of the path
// creating a name
old_i = i;
@@ -525,12 +525,26 @@ size_t Dirs::AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_
for( ; i<link_to.size() && link_to[i] != '/' ; ++i)
analyze_temp += link_to[i];
Item * pdir = GetDir(analyze_temp, dir_tab.back()->id);
if( !pdir )
return old_i; // analyze_temp is not a directory
if( analyze_temp == L".." )
{
if( dir_tab.size() <= 1 )
return false;
dir_tab.push_back(pdir);
dir_tab.pop_back();
}
else
if( analyze_temp != L"." )
{
Item * pdir = GetDir(analyze_temp, dir_tab.back()->id);
if( !pdir )
{
i = old_i;
return true; // analyze_temp is not a directory
}
dir_tab.push_back(pdir);
}
}
}
@@ -541,7 +555,10 @@ size_t Dirs::AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_
int Dirs::FollowLink(std::vector<Item*> & dir_tab, const std::wstring & link_to, std::wstring & out_item)
{
size_t i = AnalyzeDir(dir_tab, link_to);
size_t i;
if( !AnalyzeDir(dir_tab, link_to, i) )
return 2; // incorrect link_to
if( i < link_to.size() )
{
@@ -574,7 +591,7 @@ return 0;
4 - current_dir_tab was empty
current_dir_tab can be the same container as out_dir_tab
link_to can be a relative path (without the first slash)
link_to can be a relative path (without the first slash) and can contain ".." or "."
*/
int Dirs::FollowLink(const std::vector<Item*> & current_dir_tab, const std::wstring & link_to,
std::vector<Item*> & out_dir_tab, std::wstring & out_item)
@@ -693,9 +710,9 @@ Item * Dirs::CreateVarDir()
if( root )
{
v.parent_id = root->id;
v.user_id = -1;
v.group_id = -1;
v.privileges = 0755;
v.user_id = root->user_id;
v.group_id = root->group_id;
v.privileges = root->privileges;
v.subject = L"var";
v.url = L"var";
v.type = Item::dir;

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2008-2011, Tomasz Sowa
* Copyright (c) 2008-2012, Tomasz Sowa
* All rights reserved.
*
*/
@@ -47,6 +47,7 @@ public:
bool DelDir(long dir_id);
// if returns true then out_dir_tab is not empty
bool CreateDirTab(long dir_id, std::vector<Item*> & out_dir_tab);
void LogDir(const std::vector<Item*> & dir_tab);
@@ -98,7 +99,7 @@ private:
std::wstring temp_link_to;
size_t AnalyzeDir(Item * pdir, const std::wstring & path, long & dir_id, std::wstring & dir);
size_t AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_to);
bool AnalyzeDir(std::vector<Item*> & dir_tab, const std::wstring & link_to, size_t & i);
std::wstring analyze_temp;
std::wstring get_dir_temp;

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2009-2011, Tomasz Sowa
* Copyright (c) 2009-2012, Tomasz Sowa
* All rights reserved.
*
*/
@@ -53,9 +53,6 @@ void Mounts::CreateMountPar()
mount_par_image_size = AddMountPar(L"image_size");
mount_par_image_mode = AddMountPar(L"image_mode");
mount_par_image_quality = AddMountPar(L"image_quality");
//mount_par_thread = AddMountPar(L"thread");
//mount_par_createthread_on = AddMountPar(L"createthread_on");
mount_par_only_root_remove = AddMountPar(L"only_root_remove");
mount_par_emacs_on = AddMountPar(L"emacs_on");
mount_par_mkdir_on = AddMountPar(L"mkdir_on");
mount_par_app = AddMountPar(L"app");

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2009-2011, Tomasz Sowa
* Copyright (c) 2009-2012, Tomasz Sowa
* All rights reserved.
*
*/
@@ -73,9 +73,6 @@ public:
int MountParImageSize() { return mount_par_image_size; }
int MountParImageMode() { return mount_par_image_mode; }
int MountParImageQuality() { return mount_par_image_quality; }
//int MountParThread() { return mount_par_thread; }
//int MountParCreatethreadOn() { return mount_par_createthread_on; }
int MountParOnlyRootRemove() { return mount_par_only_root_remove; }
int MountParEmacsOn() { return mount_par_emacs_on; }
int MountParMkdirOn() { return mount_par_mkdir_on; }
int MountParApp() { return mount_par_app; }
@@ -148,9 +145,6 @@ private:
int mount_par_image_size;
int mount_par_image_mode;
int mount_par_image_quality;
//int mount_par_thread;
//int mount_par_createthread_on;
int mount_par_only_root_remove;
int mount_par_emacs_on;
int mount_par_mkdir_on;
int mount_par_app;

View File

@@ -29,121 +29,137 @@
// winix function and parameters have been parsed
// the request.status is OK
// (the winix function was not called yet)
#define WINIX_PREPARE_REQUEST 2000
#define WINIX_PREPARE_REQUEST 20000
// post and get functions have done their jobs
// now you can act
// this is called only if the request.status is OK
#define WINIX_PROCESS_REQUEST 2001
#define WINIX_PROCESS_REQUEST 20010
// prepere your content for displaying
// this is called after WINIX_PROCESS_REQUEST
// and when there is not a redirect
// request.status is not checked here
#define WINIX_CONTENT_MAKE 2002
#define WINIX_CONTENT_MAKE 20020
// here you can attach your own session data (based on PluginDataBase class)
// call cur->session->plugin_data.Assign(pointer)
#define WINIX_SESSION_CREATED 3000
#define WINIX_SESSION_CREATED 30000
// here you should remove your session data
// this message can be sent even if you don't assing your plugin data
#define WINIX_SESSION_REMOVE 3001
#define WINIX_SESSION_REMOVE 30010
// when a session is changed (you can save a pointer to your data here)
#define WINIX_SESSION_CHANGED 3002
#define WINIX_SESSION_CHANGED 30020
// the winix is closing
// the is not any session available (cur->session is null)
#define WINIX_CLOSE 3004
#define WINIX_CLOSE 30040
// preparing to remove a file (rm function)
// in p1 you have a pointer to the Item struct (file)
// valid members are:
// id, parent_id, type, url, file_path, file_fs, file_type, has_thumb, hash, hash_type, file_size
// user_id, group_id, privileges
// (sometimes rest members can be valid as well -- when you call directly fun_rm->RemoveFileOrSymlink() method)
#define WINIX_FILE_PREPARE_TO_REMOVE 30045
// a file or symlink was removed (rm function)
// in p1 you have a pointer to the Item struct (old file)
#define WINIX_FILE_REMOVED 3005
// directory was removed (rm function)
// PluginInfo::l1 is the dir id
#define WINIX_DIR_REMOVED 3006
// valid members are the same as in WINIX_FILE_PREPARE_TO_REMOVE
#define WINIX_FILE_REMOVED 30050
// preparing to remove a directory (rm function)
// in p1 you have a pointer to the Item struct (directory)
#define WINIX_DIR_PREPARE_TO_REMOVE 3007
// this message is sent after checking the directory permissions
// so consequently if there is no any database error then the
// directory will be removed
// and after removed WINIX_DIR_REMOVED message is sent
#define WINIX_DIR_PREPARE_TO_REMOVE 30070
// directory was removed (rm function)
// PluginInfo::l1 is the directory id
#define WINIX_DIR_REMOVED 30060
// winix is initialized,
// now you can initialize your plugin
#define WINIX_PLUGIN_INIT 3008
#define WINIX_PLUGIN_INIT 30080
// here you can add your own mount point, file systems, mount parameters
// for adding a new mount type call: system->mounts.AddMountType("new_mount_name")
#define WINIX_ADD_MOUNTS 3009
#define WINIX_ADD_MOUNTS 30090
// add plugin functions (winix functions) here
// call info.functions->Add() to add a function
#define WINIX_CREATE_FUNCTIONS 3010
#define WINIX_CREATE_FUNCTIONS 30100
// choose a default function
// if you do not select it then it will be choosen by winix
#define WINIX_SELECT_DEFAULT_FUNCTION 3011
#define WINIX_SELECT_DEFAULT_FUNCTION 30110
// /etc/fstab has been changed
// now we have new mount points
#define WINIX_FSTAB_CHANGED 3012
#define WINIX_FSTAB_CHANGED 30120
// here you add your own template to notification system
// call system->notify.AddTemplate() method
// with a template file name
#define WINIX_NOTIFY_ADD_TEMPLATE 3013
#define WINIX_NOTIFY_ADD_TEMPLATE 30130
// the request is being ended
// you can clear some of your objects here
#define WINIX_END_REQUEST 3014
#define WINIX_END_REQUEST 30140
// a new file (page) has been added
// in p1 you have a pointer to the Item struct
#define WINIX_FILE_ADDED 3015
#define WINIX_FILE_ADDED 30150
// a file (page) has been changed (edited)
// in p1 you have a pointer to the Item struct
#define WINIX_FILE_CHANGED 3016
#define WINIX_FILE_CHANGED 30160
// a file (page) has been copied
// in p1 you have a pointer to the Item struct
// not every fields of Item struct are filled
#define WINIX_FILE_COPIED 3017
#define WINIX_FILE_COPIED 30170
// a file will be moved
// in p1 you have a pointer to the Item struct
// not every fields of Item struct are filled
#define WINIX_FILE_PREPARE_TO_MOVE 3018
// valid members are:
// id, parent_id, type, url, file_path, file_fs, file_type, has_thumb, hash, hash_type, file_size
// user_id, group_id, privileges, meta
// (sometimes rest members can be valid as well -- when you call directly fun_rm->RemoveFileOrSymlink() method)
#define WINIX_FILE_PREPARE_TO_MOVE 30180
// a file has been moved
// in p1 you have a pointer to the Item struct (new file)
// not every fields of Item struct are filled
#define WINIX_FILE_MOVED 3019
// valid members are the same as in WINIX_FILE_PREPARE_TO_MOVE
#define WINIX_FILE_MOVED 30190
// a thumbnail was created
// this message is called from another thread
// the thread is called Lock() before sending this message
// in p1 you have a pointer to the Item struct
#define WINIX_CREATED_THUMB 3050
#define WINIX_CREATED_THUMB 30500
// an image has been resized
// this message is called from another thread
// the thread is called Lock() before sending this message
// in p1 you have a pointer to the Item struct
#define WINIX_IMAGE_RESIZED 3052
#define WINIX_IMAGE_RESIZED 30520
// content of a directory was sorted
// (winix 'sort' function was used)
// in p1 you have a pointer to the Item struct (of the directory)
// this is from system->dirs so you should not change the item
#define WINIX_DIR_CONTENT_SORTED 3050
#define WINIX_DIR_CONTENT_SORTED 30500
// a user has been logged
// send from 'login' winix function
// this message is also called when winix starts and reads sessions
// from the session file
#define WINIX_USER_LOGGED 3060
#define WINIX_USER_LOGGED 30600
// here you add your own html templates
@@ -154,7 +170,7 @@
// the message will be sent too whenever 'reload/templates' winix function is called
// templates you should add only in this message
// in other cases after 'reload' function the indexes would be wrong
#define WINIX_ADD_TEMPLATE 3100
#define WINIX_ADD_TEMPLATE 31000

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2010-2011, Tomasz Sowa
* Copyright (c) 2010-2012, Tomasz Sowa
* All rights reserved.
*
*/
@@ -260,12 +260,12 @@ bool System::CanChangeUser(const Item & item, long new_user_id)
// super user is allowed everything
return true;
// !! przeciez to prosciej mozna zapisac
// albo dac od razu return false
if( item.user_id != new_user_id )
if( item.user_id == -1 || new_user_id == -1 || item.user_id != new_user_id )
// only super user can change the owner of an item
return false;
// item.user_id is equal new_user_id -- we return true
return true;
}
@@ -285,10 +285,10 @@ bool System::CanChangeGroup(const Item & item, long new_group_id)
// user is allowed to change the group only if he is an owner of the item
// he can change only into a group in which he is a member of, or into a 'no_group'
if( !cur->session->puser )
if( !cur->session->puser || cur->session->puser->id == -1 )
return false;
if( cur->session->puser->id != item.user_id )
if( item.user_id == -1 || cur->session->puser->id != item.user_id )
return false;
if( new_group_id == -1 )
@@ -316,12 +316,12 @@ bool System::CanChangePrivileges(const Item & item, int new_priv)
if( item.privileges != new_priv )
{
// the owner of an item is allowed to change the privileges
if( !cur->session->puser )
// the owner of an item is allowed to change the privileges
if( !cur->session->puser || cur->session->puser->id == -1 )
return false;
if( cur->session->puser->id != item.user_id )
if( item.user_id == -1 || cur->session->puser->id != item.user_id )
return false;
}
@@ -329,7 +329,7 @@ return true;
}
// private
bool System::HasAccess(const Item & item, int mask)
{
if( !cur->session )
@@ -340,20 +340,26 @@ bool System::HasAccess(const Item & item, int mask)
// super user is allowed everything
return true;
if( cur->session->puser && cur->session->puser->id == item.user_id )
if( cur->session->puser && item.user_id != -1 && cur->session->puser->id == item.user_id )
{
// the owner
return ((item.privileges >> 9) & mask) == mask;
}
if( cur->session->puser && item.group_id != -1 && cur->session->puser->IsMemberOf(item.group_id) )
{
// group
return ((item.privileges >> 6) & mask) == mask;
}
if( cur->session->puser && cur->session->puser->IsMemberOf(item.group_id) )
if( cur->session->puser )
{
// group
// others -- others logged people
return ((item.privileges >> 3) & mask) == mask;
}
// others
// guests -- not logged people
return (item.privileges & mask) == mask;
}
@@ -381,8 +387,8 @@ bool System::HasReadExecAccess(const Item & item)
if( cur->session && cur->session->puser && cur->session->puser->super_user )
{
// there must be at least one 'x' (for the root)
return (item.privileges & 0111) != 0;
// !! CHECK ME: is it applicable to directories too?
return (item.privileges & 01111) != 0;
}
return HasAccess(item, 5); // r+x
@@ -468,6 +474,76 @@ size_t i = 0;
}
int System::NewPrivileges(int creation_mask)
{
if( cur && cur->session && cur->session->puser )
{
int umask = cur->session->puser->env.Int(L"umask", config->umask);
return (~umask) & creation_mask;
}
else
{
return (~config->umask) & creation_mask;
}
}
/*
from man sticky:
A directory whose `sticky bit' is set becomes an append-only directory,
or, more accurately, a directory in which the deletion of files is
restricted. A file in a sticky directory may only be removed or renamed
by a user if the user has write permission for the directory and the user
is the owner of the file, the owner of the directory, or the super-user.
This feature is usefully applied to directories such as /tmp which must
be publicly writable but should deny users the license to arbitrarily
delete or rename each others' files.
*/
bool System::CanRemoveRenameChild(const Item & dir, long child_item_user_id)
{
if( dir.type != Item::dir )
return false;
if( !HasWriteAccess(dir) )
return false;
if( (dir.privileges & 010000) == 0 )
// there is no a sticky bit set to this directory
return true;
if( cur->session->puser )
{
if( cur->session->puser->super_user )
return true;
if( dir.user_id != -1 && cur->session->puser->id != -1 && child_item_user_id != -1 )
{
if( cur->session->puser->id == child_item_user_id ||
cur->session->puser->id == dir.user_id )
return true;
}
}
return false;
}
int System::NewFilePrivileges()
{
return NewPrivileges(06666);
}
int System::NewDirPrivileges()
{
return NewPrivileges(07777);
}
bool System::CanUseHtml(long user_id)
{
return IsMemberOfGroup(user_id, L"allow_html");
@@ -1068,9 +1144,9 @@ bool System::AddCommonFileToVar(const wchar_t * file_path, const wchar_t * url,
file_content_item.Clear();
file_content_item.parent_id = var->id;
file_content_item.user_id = -1;
file_content_item.group_id = -1;
file_content_item.privileges = 0755;
file_content_item.user_id = var->user_id;
file_content_item.group_id = var->group_id;
file_content_item.privileges = 07555; // !! IMPROVE ME: may it should be added as a parameter to this function?
file_content_item.subject = url;
file_content_item.url = url;
file_content_item.type = Item::file;

View File

@@ -2,7 +2,7 @@
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2010-2011, Tomasz Sowa
* Copyright (c) 2010-2012, Tomasz Sowa
* All rights reserved.
*
*/
@@ -88,7 +88,8 @@ public:
bool CanChangeUser(const Item & item, long new_user_id);
bool CanChangeGroup(const Item & item, long new_group_id);
bool CanChangePrivileges(const Item & item, int new_priv);
bool HasAccess(const Item & item, int mask);
bool HasReadAccess(const Item & item);
bool HasWriteAccess(const Item & item);
bool HasReadWriteAccess(const Item & item);
@@ -99,6 +100,16 @@ public:
void CheckAccessToItems(std::vector<Item> & item_tab);
void CheckWriteAccessToItems(std::vector<Item> & item_tab);
/*
this method checks the sticky bit and write permissions
it returns true if we can remove/rename an item for the given child_item_user_id user id
*/
bool CanRemoveRenameChild(const Item & dir, long child_item_user_id);
int NewFilePrivileges();
int NewDirPrivileges();
bool CanUseHtml(long user_id);
bool CanUseBBCode(long user_id);
bool CanUseRaw(long user_id);
@@ -156,6 +167,9 @@ private:
std::vector<Item*> root_follow_dir_tab;
Item temp_follow_item;
bool HasAccess(const Item & item, int mask);
int NewPrivileges(int creation_mask);
bool CreateNewFileSimpleFs(Item & item);
bool CreateNewFileHashFs(Item & item);