Loading commands/auth/CMakeLists.txt +4 −1 Changes for commands/auth/CMakeLists.txt: 4 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ target_sources(fresh PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/su.cpp ${CMAKE_CURRENT_SOURCE_DIR}/passwd.cpp ${CMAKE_CURRENT_SOURCE_DIR}/getty.cpp ${CMAKE_CURRENT_SOURCE_DIR}/useradd.cpp ) target_include_directories(fresh PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) Loading @@ -21,6 +22,8 @@ endif() string(REGEX REPLACE "/+$" "" FRESH_PREFIX_NOSLASH "${CMAKE_INSTALL_PREFIX}") target_compile_definitions(fresh PRIVATE FRESH_SU_PATH="${FRESH_PREFIX_NOSLASH}/bin/su") add_executable(su ${CMAKE_CURRENT_SOURCE_DIR}/su_main.cpp) # ids.h (UUID and GUID ids) lives in src/ target_include_directories(su PRIVATE ${CMAKE_SOURCE_DIR}/src) if(HAVE_LIBCRYPT) target_link_libraries(su crypt) endif() Loading @@ -28,4 +31,4 @@ install(TARGETS su DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE SETUID) set(FRESH_APPLETS ${FRESH_APPLETS} login passwd getty PARENT_SCOPE) set(FRESH_APPLETS ${FRESH_APPLETS} login passwd getty useradd PARENT_SCOPE) commands/auth/authutil.h +9 −6 Changes for commands/auth/authutil.h: 9 added lines, 6 removed lines. Original line number Diff line number Diff line Loading @@ -53,15 +53,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <pwd.h> #include <shadow.h> #include "ids.h" namespace fresh { namespace auth { // uid and gid can be UUIDs and GUIDs (ids.h, user.yaml) struct PasswdEntry { std::string name,passwd,gecos,home,shell; uid_t uid=0; gid_t gid=0; uid_r_t uid=uid_r_legacy(0); gid_r_t gid=uid_r_legacy(0); }; inline void fillFromPasswd(const struct passwd *pw,PasswdEntry &out){ inline void fillFromPasswd(const struct passwd_id_r *pw,PasswdEntry &out){ out.name=pw->pw_name; out.passwd=pw->pw_passwd; out.uid=pw->pw_uid; Loading @@ -72,14 +75,14 @@ namespace fresh { namespace auth { } inline bool lookupPasswd(const std::string &username,PasswdEntry &out){ struct passwd *pw=getpwnam(username.c_str()); struct passwd_id_r *pw=getpwnam_id_r(username.c_str()); if(!pw) return false; fillFromPasswd(pw,out); return true; } inline bool lookupPasswdByUid(uid_t uid,PasswdEntry &out){ struct passwd *pw=getpwuid(uid); inline bool lookupPasswdByUid(const uid_r_t &uid,PasswdEntry &out){ struct passwd_id_r *pw=getpwuid_id_r(&uid); if(!pw) return false; fillFromPasswd(pw,out); return true; Loading commands/auth/login.cpp +2 −1 Changes for commands/auth/login.cpp: 2 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -88,7 +88,8 @@ namespace fresh { namespace cmd { return 1; } if(setgid(pe.gid)!=0 || setuid(pe.uid)!=0){ // also UUID and GUID users, with their supplementary groups if(ids::becomeUser(pe.name.c_str(),pe.uid,pe.gid)!=0){ std::cerr << "login: cannot switch to " << username << ": " << strerror(errno) << std::endl; return 1; } Loading commands/auth/passwd.cpp +4 −3 Changes for commands/auth/passwd.cpp: 4 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ namespace fresh { namespace cmd { target=argv[1]; }else{ auth::PasswdEntry me; if(auth::lookupPasswdByUid(getuid(),me)) if(auth::lookupPasswdByUid(ids::ruid(),me)) target=me.name; } if(target.empty()){ Loading @@ -66,8 +66,9 @@ namespace fresh { namespace cmd { return 1; } if(geteuid()!=0){ if(getuid()!=pe.uid){ if(!ids::isRoot(ids::euid())){ uid_r_t me=ids::ruid(); if(!uid_r_eq(&me,&pe.uid)){ std::cerr << "passwd: permission denied" << std::endl; return 1; } Loading commands/auth/suimpl.h +14 −14 Changes for commands/auth/suimpl.h: 14 added lines, 14 removed lines. Original line number Diff line number Diff line Loading @@ -50,25 +50,24 @@ namespace fresh { namespace auth { // Whether the calling user may use su at all: only members of group // "wheel" (primary gid, supplementary groups, or listed in // /etc/group.yaml's members -- login doesn't initgroups(), so the // member list is the authoritative one). No wheel group: nobody but // /etc/group.yaml's members -- the member list counts even for a // session started before the user was added). No wheel group: nobody but // root. inline bool callerInWheel(){ struct group *gr=getgrnam("wheel"); struct group_id_r *gr=getgrnam_id_r("wheel"); if(!gr) return false; gid_t wheel=gr->gr_gid; gid_r_t wheel=gr->gr_gid; PasswdEntry self; bool haveSelf=lookupPasswdByUid(getuid(),self); bool haveSelf=lookupPasswdByUid(ids::ruid(),self); if(haveSelf){ for(char **m=gr->gr_mem;m && *m;++m) if(self.name==*m) return true; if(self.gid==wheel) return true; if(uid_r_eq(&self.gid,&wheel)) return true; } if(getgid()==wheel || getegid()==wheel) return true; gid_t groups[256]; int n=getgroups(256,groups); for(int i=0;i<n;++i) if(groups[i]==wheel) return true; gid_r_t gid=ids::rgid(),egid=ids::egid(); if(uid_r_eq(&gid,&wheel) || uid_r_eq(&egid,&wheel)) return true; for(const gid_r_t &g: ids::groups()) if(uid_r_eq(&g,&wheel)) return true; return false; } Loading @@ -87,7 +86,8 @@ namespace fresh { namespace auth { else target=a; } if(getuid()!=0 && !callerInWheel()){ bool callerIsRoot=ids::isRoot(ids::ruid()); if(!callerIsRoot && !callerInWheel()){ std::cerr << "su: permission denied (not in group wheel)" << std::endl; return 1; } Loading @@ -98,7 +98,7 @@ namespace fresh { namespace auth { return 1; } if(getuid()!=0){ if(!callerIsRoot){ std::string hash; if(!lookupShadowHash(target,hash)) hash=pe.passwd; Loading @@ -112,7 +112,7 @@ namespace fresh { namespace auth { } // the target's own groups, not the caller's supplementary ones if(initgroups(pe.name.c_str(),pe.gid)!=0 || setgid(pe.gid)!=0 || setuid(pe.uid)!=0){ if(ids::becomeUser(pe.name.c_str(),pe.uid,pe.gid)!=0){ std::cerr << "su: cannot switch to " << target << ": " << strerror(errno) << std::endl; return 1; } Loading Loading
commands/auth/CMakeLists.txt +4 −1 Changes for commands/auth/CMakeLists.txt: 4 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ target_sources(fresh PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/su.cpp ${CMAKE_CURRENT_SOURCE_DIR}/passwd.cpp ${CMAKE_CURRENT_SOURCE_DIR}/getty.cpp ${CMAKE_CURRENT_SOURCE_DIR}/useradd.cpp ) target_include_directories(fresh PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) Loading @@ -21,6 +22,8 @@ endif() string(REGEX REPLACE "/+$" "" FRESH_PREFIX_NOSLASH "${CMAKE_INSTALL_PREFIX}") target_compile_definitions(fresh PRIVATE FRESH_SU_PATH="${FRESH_PREFIX_NOSLASH}/bin/su") add_executable(su ${CMAKE_CURRENT_SOURCE_DIR}/su_main.cpp) # ids.h (UUID and GUID ids) lives in src/ target_include_directories(su PRIVATE ${CMAKE_SOURCE_DIR}/src) if(HAVE_LIBCRYPT) target_link_libraries(su crypt) endif() Loading @@ -28,4 +31,4 @@ install(TARGETS su DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE SETUID) set(FRESH_APPLETS ${FRESH_APPLETS} login passwd getty PARENT_SCOPE) set(FRESH_APPLETS ${FRESH_APPLETS} login passwd getty useradd PARENT_SCOPE)
commands/auth/authutil.h +9 −6 Changes for commands/auth/authutil.h: 9 added lines, 6 removed lines. Original line number Diff line number Diff line Loading @@ -53,15 +53,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <pwd.h> #include <shadow.h> #include "ids.h" namespace fresh { namespace auth { // uid and gid can be UUIDs and GUIDs (ids.h, user.yaml) struct PasswdEntry { std::string name,passwd,gecos,home,shell; uid_t uid=0; gid_t gid=0; uid_r_t uid=uid_r_legacy(0); gid_r_t gid=uid_r_legacy(0); }; inline void fillFromPasswd(const struct passwd *pw,PasswdEntry &out){ inline void fillFromPasswd(const struct passwd_id_r *pw,PasswdEntry &out){ out.name=pw->pw_name; out.passwd=pw->pw_passwd; out.uid=pw->pw_uid; Loading @@ -72,14 +75,14 @@ namespace fresh { namespace auth { } inline bool lookupPasswd(const std::string &username,PasswdEntry &out){ struct passwd *pw=getpwnam(username.c_str()); struct passwd_id_r *pw=getpwnam_id_r(username.c_str()); if(!pw) return false; fillFromPasswd(pw,out); return true; } inline bool lookupPasswdByUid(uid_t uid,PasswdEntry &out){ struct passwd *pw=getpwuid(uid); inline bool lookupPasswdByUid(const uid_r_t &uid,PasswdEntry &out){ struct passwd_id_r *pw=getpwuid_id_r(&uid); if(!pw) return false; fillFromPasswd(pw,out); return true; Loading
commands/auth/login.cpp +2 −1 Changes for commands/auth/login.cpp: 2 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -88,7 +88,8 @@ namespace fresh { namespace cmd { return 1; } if(setgid(pe.gid)!=0 || setuid(pe.uid)!=0){ // also UUID and GUID users, with their supplementary groups if(ids::becomeUser(pe.name.c_str(),pe.uid,pe.gid)!=0){ std::cerr << "login: cannot switch to " << username << ": " << strerror(errno) << std::endl; return 1; } Loading
commands/auth/passwd.cpp +4 −3 Changes for commands/auth/passwd.cpp: 4 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ namespace fresh { namespace cmd { target=argv[1]; }else{ auth::PasswdEntry me; if(auth::lookupPasswdByUid(getuid(),me)) if(auth::lookupPasswdByUid(ids::ruid(),me)) target=me.name; } if(target.empty()){ Loading @@ -66,8 +66,9 @@ namespace fresh { namespace cmd { return 1; } if(geteuid()!=0){ if(getuid()!=pe.uid){ if(!ids::isRoot(ids::euid())){ uid_r_t me=ids::ruid(); if(!uid_r_eq(&me,&pe.uid)){ std::cerr << "passwd: permission denied" << std::endl; return 1; } Loading
commands/auth/suimpl.h +14 −14 Changes for commands/auth/suimpl.h: 14 added lines, 14 removed lines. Original line number Diff line number Diff line Loading @@ -50,25 +50,24 @@ namespace fresh { namespace auth { // Whether the calling user may use su at all: only members of group // "wheel" (primary gid, supplementary groups, or listed in // /etc/group.yaml's members -- login doesn't initgroups(), so the // member list is the authoritative one). No wheel group: nobody but // /etc/group.yaml's members -- the member list counts even for a // session started before the user was added). No wheel group: nobody but // root. inline bool callerInWheel(){ struct group *gr=getgrnam("wheel"); struct group_id_r *gr=getgrnam_id_r("wheel"); if(!gr) return false; gid_t wheel=gr->gr_gid; gid_r_t wheel=gr->gr_gid; PasswdEntry self; bool haveSelf=lookupPasswdByUid(getuid(),self); bool haveSelf=lookupPasswdByUid(ids::ruid(),self); if(haveSelf){ for(char **m=gr->gr_mem;m && *m;++m) if(self.name==*m) return true; if(self.gid==wheel) return true; if(uid_r_eq(&self.gid,&wheel)) return true; } if(getgid()==wheel || getegid()==wheel) return true; gid_t groups[256]; int n=getgroups(256,groups); for(int i=0;i<n;++i) if(groups[i]==wheel) return true; gid_r_t gid=ids::rgid(),egid=ids::egid(); if(uid_r_eq(&gid,&wheel) || uid_r_eq(&egid,&wheel)) return true; for(const gid_r_t &g: ids::groups()) if(uid_r_eq(&g,&wheel)) return true; return false; } Loading @@ -87,7 +86,8 @@ namespace fresh { namespace auth { else target=a; } if(getuid()!=0 && !callerInWheel()){ bool callerIsRoot=ids::isRoot(ids::ruid()); if(!callerIsRoot && !callerInWheel()){ std::cerr << "su: permission denied (not in group wheel)" << std::endl; return 1; } Loading @@ -98,7 +98,7 @@ namespace fresh { namespace auth { return 1; } if(getuid()!=0){ if(!callerIsRoot){ std::string hash; if(!lookupShadowHash(target,hash)) hash=pe.passwd; Loading @@ -112,7 +112,7 @@ namespace fresh { namespace auth { } // the target's own groups, not the caller's supplementary ones if(initgroups(pe.name.c_str(),pe.gid)!=0 || setgid(pe.gid)!=0 || setuid(pe.uid)!=0){ if(ids::becomeUser(pe.name.c_str(),pe.uid,pe.gid)!=0){ std::cerr << "su: cannot switch to " << target << ": " << strerror(errno) << std::endl; return 1; } Loading