From: Arvin Schnell Date: Thu, 31 Jul 2014 13:54:34 +0000 (+0200) Subject: - also handle primary group of user when checking permissions (see gh#openSUSE/snappe... X-Git-Tag: v0.2.4~6^2 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=018eea8c23623643b4abebdd4ebf070d41e722dc;p=thirdparty%2Fsnapper.git - also handle primary group of user when checking permissions (see gh#openSUSE/snapper#100) --- diff --git a/package/snapper.changes b/package/snapper.changes index ab4d781c..08af4cd7 100644 --- a/package/snapper.changes +++ b/package/snapper.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Thu Jul 31 15:38:16 CEST 2014 - aschnell@suse.de + +- also handle primary group of user when checking permissions + (see gh#openSUSE/snapper#100) + ------------------------------------------------------------------- Fri Jul 25 12:38:33 CEST 2014 - aschnell@suse.de diff --git a/server/Client.cc b/server/Client.cc index 52c2b21d..d5ee8205 100644 --- a/server/Client.cc +++ b/server/Client.cc @@ -382,12 +382,33 @@ Client::check_permission(DBus::Connection& conn, DBus::Message& msg, const MetaSnapper& meta_snapper) const { unsigned long uid = conn.get_unix_userid(msg); + + // Check if the uid of the dbus-user is root. if (uid == 0) return; - if (find(meta_snapper.uids.begin(), meta_snapper.uids.end(), uid) != meta_snapper.uids.end()) + // Check if the uid of the dbus-user is included in the allowed uids. + if (contains(meta_snapper.uids, uid)) return; + string username; + gid_t gid; + + if (get_uid_username_gid(uid, username, gid)) + { + // Check if the primary gid of the dbus-user is included in the allowed gids. + if (contains(meta_snapper.gids, gid)) + return; + + vector gids = getgrouplist(username.c_str(), gid); + + // Check if any (primary or secondary) gid of the dbus-user is included in the allowed + // gids. + for (vector::const_iterator it = gids.begin(); it != gids.end(); ++it) + if (contains(meta_snapper.gids, *it)) + return; + } + throw Permissions(); } diff --git a/server/MetaSnapper.cc b/server/MetaSnapper.cc index 31686965..941c18ff 100644 --- a/server/MetaSnapper.cc +++ b/server/MetaSnapper.cc @@ -147,19 +147,24 @@ MetaSnapper::set_permissions() } } + sort(uids.begin(), uids.end()); + uids.erase(unique(uids.begin(), uids.end()), uids.end()); + + gids.clear(); + vector groups; if (config_info.getValue(KEY_ALLOW_GROUPS, groups)) { for (vector::const_iterator it = groups.begin(); it != groups.end(); ++it) { - vector tmp; - if (get_group_uids(it->c_str(), tmp)) - uids.insert(uids.end(), tmp.begin(), tmp.end()); + gid_t tmp; + if (get_group_gid(it->c_str(), tmp)) + gids.push_back(tmp); } } - sort(uids.begin(), uids.end()); - uids.erase(unique(uids.begin(), uids.end()), uids.end()); + sort(gids.begin(), gids.end()); + gids.erase(unique(gids.begin(), gids.end()), gids.end()); } diff --git a/server/MetaSnapper.h b/server/MetaSnapper.h index 4afda9e7..e570a5d2 100644 --- a/server/MetaSnapper.h +++ b/server/MetaSnapper.h @@ -95,6 +95,7 @@ public: void setConfigInfo(const map& raw); vector uids; + vector gids; Snapper* getSnapper(); diff --git a/snapper/AppUtil.cc b/snapper/AppUtil.cc index b7d3a4cd..681f332b 100644 --- a/snapper/AppUtil.cc +++ b/snapper/AppUtil.cc @@ -281,7 +281,7 @@ namespace snapper bool - get_user_uid(const char* username, uid_t& uid) + get_uid_username_gid(uid_t uid, string& username, gid_t& gid) { struct passwd pwd; struct passwd* result; @@ -289,45 +289,36 @@ namespace snapper long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); char buf[bufsize]; - if (getpwnam_r(username, &pwd, buf, bufsize, &result) != 0 || result != &pwd) - { - y2war("couldn't find username '" << username << "'"); + if (getpwuid_r(uid, &pwd, buf, bufsize, &result) != 0 || result != &pwd) return false; - } memset(pwd.pw_passwd, 0, strlen(pwd.pw_passwd)); - uid = pwd.pw_uid; + username = pwd.pw_name; + gid = pwd.pw_gid; return true; } bool - get_group_uids(const char* groupname, vector& uids) + get_user_uid(const char* username, uid_t& uid) { - struct group grp; - struct group* result; + struct passwd pwd; + struct passwd* result; - long bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); + long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); char buf[bufsize]; - if (getgrnam_r(groupname, &grp, buf, bufsize, &result) != 0 || result != &grp) + if (getpwnam_r(username, &pwd, buf, bufsize, &result) != 0 || result != &pwd) { - y2war("couldn't find groupname '" << groupname << "'"); + y2war("couldn't find username '" << username << "'"); return false; } - memset(grp.gr_passwd, 0, strlen(grp.gr_passwd)); - - uids.clear(); + memset(pwd.pw_passwd, 0, strlen(pwd.pw_passwd)); - for (char** p = grp.gr_mem; *p != NULL; ++p) - { - uid_t uid; - if (get_user_uid(*p, uid)) - uids.push_back(uid); - } + uid = pwd.pw_uid; return true; } @@ -356,6 +347,27 @@ namespace snapper } + vector + getgrouplist(const char* username, gid_t gid) + { + int n = 16; + gid_t* buf = (gid_t*) malloc(sizeof(gid_t) * n); + + if (::getgrouplist(username, gid, buf, &n) == -1) + { + buf = (gid_t*) realloc(buf, sizeof(gid_t) * n); + ::getgrouplist(username, gid, buf, &n); + } + + vector gids(&buf[0], &buf[n]); + sort(gids.begin(), gids.end()); + + free(buf); + + return gids; + } + + StopWatch::StopWatch() { gettimeofday(&start_tv, NULL); diff --git a/snapper/AppUtil.h b/snapper/AppUtil.h index 05609925..1afb9c94 100644 --- a/snapper/AppUtil.h +++ b/snapper/AppUtil.h @@ -86,10 +86,10 @@ namespace snapper time_t scan_datetime(const string& str, bool utc); string username(uid_t uid); - + bool get_uid_username_gid(uid_t uid, string& username, gid_t& gid); bool get_user_uid(const char* username, uid_t& uid); bool get_group_gid(const char* groupname, gid_t& gid); - bool get_group_uids(const char* groupname, vector& uids); + vector getgrouplist(const char* username, gid_t gid); class StopWatch