Module: Puppet::Util::SUIDManager
Class Method Summary collapse
-
.asuser(new_uid = nil, new_gid = nil) ⇒ Object
Runs block setting euid and egid if provided then restoring original ids.
-
.change_group(group, permanently = false) ⇒ Object
Changes the egid of the process if ‘permanently` is not set, otherwise changes gid.
-
.change_privileges(uid = nil, gid = nil, permanently = false) ⇒ Object
If ‘permanently` is set, will permanently change the uid/gid of the process.
-
.change_user(user, permanently = false) ⇒ Object
As change_group, but operates on uids.
-
.convert_xid(type, id) ⇒ Object
Make sure the passed argument is a number.
- .groups=(grouplist) ⇒ Object
-
.initgroups(uid) ⇒ Object
Initialize primary and supplemental groups to those of the target user.
- .osx_maj_ver ⇒ Object
- .root? ⇒ Boolean
Methods included from Warnings
clear_warnings, debug_once, maybe_log, notice_once, warnonce
Class Method Details
.asuser(new_uid = nil, new_gid = nil) ⇒ Object
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.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/puppet/util/suidmanager.rb', line 63 def asuser(new_uid = nil, new_gid = nil) return yield if Puppet::Util::Platform.windows? return yield unless root? return yield unless new_uid or new_gid old_euid = euid old_egid = egid begin change_privileges(new_uid, new_gid, false) yield ensure change_privileges(new_uid ? old_euid : nil, old_egid, false) end end |
.change_group(group, permanently = false) ⇒ Object
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.
101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/puppet/util/suidmanager.rb', line 101 def change_group(group, permanently = false) gid = convert_xid(:gid, group) raise Puppet::Error, _("No such group %{group}") % { group: group } unless gid return if Process.egid == gid if permanently Process::GID.change_privilege(gid) else Process.egid = gid end end |
.change_privileges(uid = nil, gid = nil, permanently = false) ⇒ Object
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.
85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/puppet/util/suidmanager.rb', line 85 def change_privileges(uid = nil, gid = nil, permanently = false) return unless uid or gid unless gid uid = convert_xid(:uid, uid) gid = Etc.getpwuid(uid).gid end change_group(gid, permanently) change_user(uid, permanently) if uid end |
.change_user(user, permanently = false) ⇒ Object
As change_group, but operates on uids. If changing user permanently, supplementary groups will be set the to default groups for the new uid.
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/puppet/util/suidmanager.rb', line 117 def change_user(user, permanently = false) uid = convert_xid(:uid, user) raise Puppet::Error, _("No such user %{user}") % { user: user } unless uid return if Process.euid == uid if permanently # If changing uid, we must be root. So initgroups first here. initgroups(uid) Process::UID.change_privilege(uid) elsif Process.euid == 0 # We must be root to initgroups, so initgroups before dropping euid if # we're root, otherwise elevate euid before initgroups. # change euid (to root) first. initgroups(uid) Process.euid = uid else Process.euid = uid initgroups(uid) end end |
.convert_xid(type, id) ⇒ Object
Make sure the passed argument is a number.
142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/puppet/util/suidmanager.rb', line 142 def convert_xid(type, id) return id if id.is_a? Integer map = { :gid => :group, :uid => :user } raise ArgumentError, _("Invalid id type %{type}") % { type: type } unless map.include?(type) ret = Puppet::Util.send(type, id) if ret.nil? raise Puppet::Error, _("Invalid %{klass}: %{id}") % { klass: map[type], id: id } end ret end |
.groups=(grouplist) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/puppet/util/suidmanager.rb', line 27 def groups=(grouplist) Process.groups = grouplist rescue Errno::EINVAL => e # We catch Errno::EINVAL as some operating systems (OS X in particular) can # cause troubles when using Process#groups= to change *this* user / process # list of supplementary groups membership. This is done via Ruby's function # "static VALUE proc_setgroups(VALUE obj, VALUE ary)" which is effectively # a wrapper for "int setgroups(size_t size, const gid_t *list)" (part of SVr4 # and 4.3BSD but not in POSIX.1-2001) that fails and sets errno to EINVAL. # # This does not appear to be a problem with Ruby but rather an issue on the # operating system side. Therefore we catch the exception and look whether # we run under OS X or not -- if so, then we acknowledge the problem and # re-throw the exception otherwise. if !osx_maj_ver || osx_maj_ver.empty? raise e end end |
.initgroups(uid) ⇒ Object
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.
161 162 163 164 |
# File 'lib/puppet/util/suidmanager.rb', line 161 def initgroups(uid) pwent = Etc.getpwuid(uid) Process.initgroups(pwent.name, pwent.gid) end |