Loading src/files.cpp +61 −18 Changes for src/files.cpp: 61 added lines, 18 removed lines. Original line number Diff line number Diff line Loading @@ -155,24 +155,70 @@ bool inheritOwner(int fd, int dir, const struct stat &st) { return fchown(fd, st.st_uid, st.st_gid) == 0; } bool parseId(const std::string &v, bool group, unsigned &out) { // An owner or group to set: classic, or (systempp) a UUID or GUID one; // unset leaves it unchanged. #ifdef SHAREDD_UID_R struct OwnerId { uid_r_t id = uid_r_none(); bool set() const { return id.type != UID_R_NONE; } }; #else struct OwnerId { unsigned id = (unsigned)-1; bool set() const { return id != (unsigned)-1; } }; #endif // a name, a number or (systempp) an id's text form bool parseId(const std::string &v, bool group, OwnerId &out) { if (!v.empty() && v.find_first_not_of("0123456789") == std::string::npos) { out = (unsigned)std::strtoul(v.c_str(), nullptr, 10); unsigned n = (unsigned)std::strtoul(v.c_str(), nullptr, 10); #ifdef SHAREDD_UID_R out.id = uid_r_legacy(n); #else out.id = n; #endif return true; } #ifdef SHAREDD_UID_R if (group) { if (struct group_id_r *gr = getgrnam_id_r(v.c_str())) { out.id = gr->gr_gid; return true; } } else if (struct passwd_id_r *pw = getpwnam_id_r(v.c_str())) { out.id = pw->pw_uid; return true; } return uid_r_from_str(v.c_str(), &out.id) == 0 && !uid_r_is_legacy(&out.id); #else if (group) { struct group *gr = getgrnam(v.c_str()); if (gr) out = gr->gr_gid; if (gr) out.id = gr->gr_gid; return gr != nullptr; } struct passwd *pw = getpwnam(v.c_str()); if (pw) out = pw->pw_uid; if (pw) out.id = pw->pw_uid; return pw != nullptr; #endif } bool chownFd(int fd, const OwnerId &uid, const OwnerId &gid) { if (!uid.set() && !gid.set()) return true; #ifdef SHAREDD_UID_R if (fchown_r(fd, &uid.id, &gid.id) == 0) return true; if (errno != ENOSYS || (uid.set() && !uid_r_is_legacy(&uid.id)) || (gid.set() && !uid_r_is_legacy(&gid.id))) return false; // a kernel without the *_r calls: classic ids only return fchown(fd, uid.set() ? uid.id.legacy : (uid_t)-1, gid.set() ? gid.id.legacy : (gid_t)-1) == 0; #else return fchown(fd, uid.id, gid.id) == 0; #endif } // owner, group and mode on an open file descriptor bool apply(int fd, bool isDir, uid_t uid, gid_t gid, int mode) { if ((uid != (uid_t)-1 || gid != (gid_t)-1) && fchown(fd, uid, gid) != 0) return false; bool apply(int fd, bool isDir, const OwnerId &uid, const OwnerId &gid, int mode) { if (!chownFd(fd, uid, gid)) return false; if (mode >= 0) { unsigned m = (unsigned)mode & AllowedModes; if (!isDir) m &= 0666u; // files: read/write only -- no execute, setgid or sticky Loading @@ -198,7 +244,7 @@ Fd openEntry(int dir, const char *name, bool &isDir) { } // everything below dir; failures are counted, the walk goes on void applyTree(int dir, uid_t uid, gid_t gid, int mode, int &failed) { void applyTree(int dir, const OwnerId &uid, const OwnerId &gid, int mode, int &failed) { DIR *d = fdopendir(dup(dir)); if (!d) { ++failed; Loading Loading @@ -287,19 +333,16 @@ std::string setPermissions(const Share &s, const std::string &rel, const std::st const std::string &group, int mode, bool recursive, const std::string &lang) { std::vector<std::string> parts; if (!split(rel, parts)) return tr(lang, "invalid path", "ungültiger Pfad"); uid_t uid = (uid_t)-1; gid_t gid = (gid_t)-1; unsigned id; if (!owner.empty()) { if (!parseId(owner, false, id)) return tr(lang, "no user %1", "kein Benutzer %1", {owner}); uid = id; } if (!group.empty()) { if (!parseId(group, true, id)) return tr(lang, "no group %1", "keine Gruppe %1", {group}); gid = id; } OwnerId uid, gid; if (!owner.empty() && !parseId(owner, false, uid)) return tr(lang, "no user %1", "kein Benutzer %1", {owner}); if (!group.empty() && !parseId(group, true, gid)) return tr(lang, "no group %1", "keine Gruppe %1", {group}); #ifdef SHAREDD_UID_R endpwent_id_r(); endgrent_id_r(); #else endpwent(); endgrent(); #endif if (mode >= 0 && ((unsigned)mode & ~AllowedModes)) return tr(lang, "invalid mode (setuid isn't allowed)", "ungültige Rechte (setuid ist nicht erlaubt)"); Loading Loading
src/files.cpp +61 −18 Changes for src/files.cpp: 61 added lines, 18 removed lines. Original line number Diff line number Diff line Loading @@ -155,24 +155,70 @@ bool inheritOwner(int fd, int dir, const struct stat &st) { return fchown(fd, st.st_uid, st.st_gid) == 0; } bool parseId(const std::string &v, bool group, unsigned &out) { // An owner or group to set: classic, or (systempp) a UUID or GUID one; // unset leaves it unchanged. #ifdef SHAREDD_UID_R struct OwnerId { uid_r_t id = uid_r_none(); bool set() const { return id.type != UID_R_NONE; } }; #else struct OwnerId { unsigned id = (unsigned)-1; bool set() const { return id != (unsigned)-1; } }; #endif // a name, a number or (systempp) an id's text form bool parseId(const std::string &v, bool group, OwnerId &out) { if (!v.empty() && v.find_first_not_of("0123456789") == std::string::npos) { out = (unsigned)std::strtoul(v.c_str(), nullptr, 10); unsigned n = (unsigned)std::strtoul(v.c_str(), nullptr, 10); #ifdef SHAREDD_UID_R out.id = uid_r_legacy(n); #else out.id = n; #endif return true; } #ifdef SHAREDD_UID_R if (group) { if (struct group_id_r *gr = getgrnam_id_r(v.c_str())) { out.id = gr->gr_gid; return true; } } else if (struct passwd_id_r *pw = getpwnam_id_r(v.c_str())) { out.id = pw->pw_uid; return true; } return uid_r_from_str(v.c_str(), &out.id) == 0 && !uid_r_is_legacy(&out.id); #else if (group) { struct group *gr = getgrnam(v.c_str()); if (gr) out = gr->gr_gid; if (gr) out.id = gr->gr_gid; return gr != nullptr; } struct passwd *pw = getpwnam(v.c_str()); if (pw) out = pw->pw_uid; if (pw) out.id = pw->pw_uid; return pw != nullptr; #endif } bool chownFd(int fd, const OwnerId &uid, const OwnerId &gid) { if (!uid.set() && !gid.set()) return true; #ifdef SHAREDD_UID_R if (fchown_r(fd, &uid.id, &gid.id) == 0) return true; if (errno != ENOSYS || (uid.set() && !uid_r_is_legacy(&uid.id)) || (gid.set() && !uid_r_is_legacy(&gid.id))) return false; // a kernel without the *_r calls: classic ids only return fchown(fd, uid.set() ? uid.id.legacy : (uid_t)-1, gid.set() ? gid.id.legacy : (gid_t)-1) == 0; #else return fchown(fd, uid.id, gid.id) == 0; #endif } // owner, group and mode on an open file descriptor bool apply(int fd, bool isDir, uid_t uid, gid_t gid, int mode) { if ((uid != (uid_t)-1 || gid != (gid_t)-1) && fchown(fd, uid, gid) != 0) return false; bool apply(int fd, bool isDir, const OwnerId &uid, const OwnerId &gid, int mode) { if (!chownFd(fd, uid, gid)) return false; if (mode >= 0) { unsigned m = (unsigned)mode & AllowedModes; if (!isDir) m &= 0666u; // files: read/write only -- no execute, setgid or sticky Loading @@ -198,7 +244,7 @@ Fd openEntry(int dir, const char *name, bool &isDir) { } // everything below dir; failures are counted, the walk goes on void applyTree(int dir, uid_t uid, gid_t gid, int mode, int &failed) { void applyTree(int dir, const OwnerId &uid, const OwnerId &gid, int mode, int &failed) { DIR *d = fdopendir(dup(dir)); if (!d) { ++failed; Loading Loading @@ -287,19 +333,16 @@ std::string setPermissions(const Share &s, const std::string &rel, const std::st const std::string &group, int mode, bool recursive, const std::string &lang) { std::vector<std::string> parts; if (!split(rel, parts)) return tr(lang, "invalid path", "ungültiger Pfad"); uid_t uid = (uid_t)-1; gid_t gid = (gid_t)-1; unsigned id; if (!owner.empty()) { if (!parseId(owner, false, id)) return tr(lang, "no user %1", "kein Benutzer %1", {owner}); uid = id; } if (!group.empty()) { if (!parseId(group, true, id)) return tr(lang, "no group %1", "keine Gruppe %1", {group}); gid = id; } OwnerId uid, gid; if (!owner.empty() && !parseId(owner, false, uid)) return tr(lang, "no user %1", "kein Benutzer %1", {owner}); if (!group.empty() && !parseId(group, true, gid)) return tr(lang, "no group %1", "keine Gruppe %1", {group}); #ifdef SHAREDD_UID_R endpwent_id_r(); endgrent_id_r(); #else endpwent(); endgrent(); #endif if (mode >= 0 && ((unsigned)mode & ~AllowedModes)) return tr(lang, "invalid mode (setuid isn't allowed)", "ungültige Rechte (setuid ist nicht erlaubt)"); Loading