module Puppet::Util::SUIDManager
Public Class Methods
Runs block setting euid and egid if provided then restoring original ids. If running on Windows
or without root, the block will be run with the current euid/egid.
# File lib/puppet/util/suidmanager.rb 65 def asuser(new_uid=nil, new_gid=nil) 66 return yield if Puppet::Util::Platform.windows? 67 return yield unless root? 68 return yield unless new_uid or new_gid 69 70 old_euid, old_egid = self.euid, self.egid 71 begin 72 change_privileges(new_uid, new_gid, false) 73 74 yield 75 ensure 76 change_privileges(new_uid ? old_euid : nil, old_egid, false) 77 end 78 end
Changes the egid of the process if `permanently` is not set, otherwise changes gid. This method will fail if used on Windows
, or attempting to change to a different gid without root.
# File lib/puppet/util/suidmanager.rb 102 def change_group(group, permanently=false) 103 gid = convert_xid(:gid, group) 104 raise Puppet::Error, _("No such group %{group}") % { group: group } unless gid 105 106 return if Process.egid == gid 107 108 if permanently 109 Process::GID.change_privilege(gid) 110 else 111 Process.egid = gid 112 end 113 end
If `permanently` is set, will permanently change the uid/gid of the process. If not, it will only set the euid/egid. If only uid is supplied, the primary group of the supplied gid will be used. If only gid is supplied, only gid will be changed. This method will fail if used on Windows
.
# File lib/puppet/util/suidmanager.rb 86 def change_privileges(uid=nil, gid=nil, permanently=false) 87 return unless uid or gid 88 89 unless gid 90 uid = convert_xid(:uid, uid) 91 gid = Etc.getpwuid(uid).gid 92 end 93 94 change_group(gid, permanently) 95 change_user(uid, permanently) if uid 96 end
As change_group
, but operates on uids. If changing user permanently, supplementary groups will be set the to default groups for the new uid.
# File lib/puppet/util/suidmanager.rb 118 def change_user(user, permanently=false) 119 uid = convert_xid(:uid, user) 120 raise Puppet::Error, _("No such user %{user}") % { user: user } unless uid 121 122 return if Process.euid == uid 123 124 if permanently 125 # If changing uid, we must be root. So initgroups first here. 126 initgroups(uid) 127 128 Process::UID.change_privilege(uid) 129 else 130 # We must be root to initgroups, so initgroups before dropping euid if 131 # we're root, otherwise elevate euid before initgroups. 132 # change euid (to root) first. 133 if Process.euid == 0 134 initgroups(uid) 135 Process.euid = uid 136 else 137 Process.euid = uid 138 initgroups(uid) 139 end 140 end 141 end
Make sure the passed argument is a number.
# File lib/puppet/util/suidmanager.rb 145 def convert_xid(type, id) 146 return id if id.kind_of? Integer 147 map = {:gid => :group, :uid => :user} 148 raise ArgumentError, _("Invalid id type %{type}") % { type: type } unless map.include?(type) 149 ret = Puppet::Util.send(type, id) 150 if ret == nil 151 raise Puppet::Error, _("Invalid %{klass}: %{id}") % { klass: map[type], id: id } 152 end 153 ret 154 end
# File lib/puppet/util/suidmanager.rb 25 def groups=(grouplist) 26 begin 27 return Process.groups = grouplist 28 rescue Errno::EINVAL => e 29 #We catch Errno::EINVAL as some operating systems (OS X in particular) can 30 # cause troubles when using Process#groups= to change *this* user / process 31 # list of supplementary groups membership. This is done via Ruby's function 32 # "static VALUE proc_setgroups(VALUE obj, VALUE ary)" which is effectively 33 # a wrapper for "int setgroups(size_t size, const gid_t *list)" (part of SVr4 34 # and 4.3BSD but not in POSIX.1-2001) that fails and sets errno to EINVAL. 35 # 36 # This does not appear to be a problem with Ruby but rather an issue on the 37 # operating system side. Therefore we catch the exception and look whether 38 # we run under OS X or not -- if so, then we acknowledge the problem and 39 # re-throw the exception otherwise. 40 if osx_maj_ver and not osx_maj_ver.empty? 41 return true 42 else 43 raise e 44 end 45 end 46 end
Initialize primary and supplemental groups to those of the target user. We take the UID and manually look up their details in the system database, including username and primary group. This method will fail on Windows
, or if used without root to initgroups of another user.
# File lib/puppet/util/suidmanager.rb 161 def initgroups(uid) 162 pwent = Etc.getpwuid(uid) 163 Process.initgroups(pwent.name, pwent.gid) 164 end
# File lib/puppet/util/suidmanager.rb 19 def osx_maj_ver 20 return @osx_maj_ver unless @osx_maj_ver.nil? 21 @osx_maj_ver = Facter.value('macosx_productversion_major') || false 22 end
# File lib/puppet/util/suidmanager.rb 49 def self.root? 50 if Puppet::Util::Platform.windows? 51 require_relative '../../puppet/util/windows/user' 52 Puppet::Util::Windows::User.admin? 53 else 54 Process.uid == 0 55 end 56 end
Private Instance Methods
Runs block setting euid and egid if provided then restoring original ids. If running on Windows
or without root, the block will be run with the current euid/egid.
# File lib/puppet/util/suidmanager.rb 65 def asuser(new_uid=nil, new_gid=nil) 66 return yield if Puppet::Util::Platform.windows? 67 return yield unless root? 68 return yield unless new_uid or new_gid 69 70 old_euid, old_egid = self.euid, self.egid 71 begin 72 change_privileges(new_uid, new_gid, false) 73 74 yield 75 ensure 76 change_privileges(new_uid ? old_euid : nil, old_egid, false) 77 end 78 end
Changes the egid of the process if `permanently` is not set, otherwise changes gid. This method will fail if used on Windows
, or attempting to change to a different gid without root.
# File lib/puppet/util/suidmanager.rb 102 def change_group(group, permanently=false) 103 gid = convert_xid(:gid, group) 104 raise Puppet::Error, _("No such group %{group}") % { group: group } unless gid 105 106 return if Process.egid == gid 107 108 if permanently 109 Process::GID.change_privilege(gid) 110 else 111 Process.egid = gid 112 end 113 end
If `permanently` is set, will permanently change the uid/gid of the process. If not, it will only set the euid/egid. If only uid is supplied, the primary group of the supplied gid will be used. If only gid is supplied, only gid will be changed. This method will fail if used on Windows
.
# File lib/puppet/util/suidmanager.rb 86 def change_privileges(uid=nil, gid=nil, permanently=false) 87 return unless uid or gid 88 89 unless gid 90 uid = convert_xid(:uid, uid) 91 gid = Etc.getpwuid(uid).gid 92 end 93 94 change_group(gid, permanently) 95 change_user(uid, permanently) if uid 96 end
As change_group
, but operates on uids. If changing user permanently, supplementary groups will be set the to default groups for the new uid.
# File lib/puppet/util/suidmanager.rb 118 def change_user(user, permanently=false) 119 uid = convert_xid(:uid, user) 120 raise Puppet::Error, _("No such user %{user}") % { user: user } unless uid 121 122 return if Process.euid == uid 123 124 if permanently 125 # If changing uid, we must be root. So initgroups first here. 126 initgroups(uid) 127 128 Process::UID.change_privilege(uid) 129 else 130 # We must be root to initgroups, so initgroups before dropping euid if 131 # we're root, otherwise elevate euid before initgroups. 132 # change euid (to root) first. 133 if Process.euid == 0 134 initgroups(uid) 135 Process.euid = uid 136 else 137 Process.euid = uid 138 initgroups(uid) 139 end 140 end 141 end
Make sure the passed argument is a number.
# File lib/puppet/util/suidmanager.rb 145 def convert_xid(type, id) 146 return id if id.kind_of? Integer 147 map = {:gid => :group, :uid => :user} 148 raise ArgumentError, _("Invalid id type %{type}") % { type: type } unless map.include?(type) 149 ret = Puppet::Util.send(type, id) 150 if ret == nil 151 raise Puppet::Error, _("Invalid %{klass}: %{id}") % { klass: map[type], id: id } 152 end 153 ret 154 end
# File lib/puppet/util/suidmanager.rb 25 def groups=(grouplist) 26 begin 27 return Process.groups = grouplist 28 rescue Errno::EINVAL => e 29 #We catch Errno::EINVAL as some operating systems (OS X in particular) can 30 # cause troubles when using Process#groups= to change *this* user / process 31 # list of supplementary groups membership. This is done via Ruby's function 32 # "static VALUE proc_setgroups(VALUE obj, VALUE ary)" which is effectively 33 # a wrapper for "int setgroups(size_t size, const gid_t *list)" (part of SVr4 34 # and 4.3BSD but not in POSIX.1-2001) that fails and sets errno to EINVAL. 35 # 36 # This does not appear to be a problem with Ruby but rather an issue on the 37 # operating system side. Therefore we catch the exception and look whether 38 # we run under OS X or not -- if so, then we acknowledge the problem and 39 # re-throw the exception otherwise. 40 if osx_maj_ver and not osx_maj_ver.empty? 41 return true 42 else 43 raise e 44 end 45 end 46 end
Initialize primary and supplemental groups to those of the target user. We take the UID and manually look up their details in the system database, including username and primary group. This method will fail on Windows
, or if used without root to initgroups of another user.
# File lib/puppet/util/suidmanager.rb 161 def initgroups(uid) 162 pwent = Etc.getpwuid(uid) 163 Process.initgroups(pwent.name, pwent.gid) 164 end
# File lib/puppet/util/suidmanager.rb 19 def osx_maj_ver 20 return @osx_maj_ver unless @osx_maj_ver.nil? 21 @osx_maj_ver = Facter.value('macosx_productversion_major') || false 22 end