1 # data.py -- Calculated/Discovered Data Values
2 # Copyright 1998-2010 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
5 import os, pwd, grp, platform
8 portage.proxy.lazyimport.lazyimport(globals(),
9 'portage.output:colorize',
10 'portage.util:writemsg',
12 from portage.localization import _
14 ostype=platform.system()
16 if ostype == "DragonFly" or ostype.endswith("BSD"):
21 lchown = getattr(os, "lchown", None)
24 if ostype == "Darwin":
25 def lchown(*pos_args, **key_args):
28 def lchown(*pargs, **kwargs):
29 writemsg(colorize("BAD", "!!!") + _(
30 " It seems that os.lchown does not"
31 " exist. Please rebuild python.\n"), noiselevel=-1)
34 lchown = portage._unicode_func_wrapper(lchown)
36 def portage_group_warning():
37 warn_prefix = colorize("BAD", "*** WARNING *** ")
39 "For security reasons, only system administrators should be",
40 "allowed in the portage group. Untrusted users or processes",
41 "can potentially exploit the portage group for attacks such as",
42 "local privilege escalation."
45 writemsg(warn_prefix, noiselevel=-1)
46 writemsg(x, noiselevel=-1)
47 writemsg("\n", noiselevel=-1)
48 writemsg("\n", noiselevel=-1)
50 # Portage has 3 security levels that depend on the uid and gid of the main
51 # process and are assigned according to the following table:
53 # Privileges secpass uid gid
55 # group 1 any portage_gid
58 # If the "wheel" group does not exist then wheelgid falls back to 0.
59 # If the "portage" group does not exist then portage_uid falls back to wheelgid.
69 wheelgid=grp.getgrnam("wheel")[2]
73 # Allow the overriding of the user used for 'userpriv' and 'userfetch'
74 _portage_uname = os.environ.get('PORTAGE_USERNAME', 'portage')
75 _portage_grpname = os.environ.get('PORTAGE_GRPNAME', 'portage')
77 #Discover the uid and gid of the portage user/group
79 portage_uid = pwd.getpwnam(_portage_uname)[2]
80 portage_gid = grp.getgrnam(_portage_grpname)[2]
81 if secpass < 1 and portage_gid in os.getgroups():
86 userpriv_groups = [portage_gid]
87 writemsg(colorize("BAD",
88 _("portage: 'portage' user or group missing.")) + "\n", noiselevel=-1)
90 " For the defaults, line 1 goes into passwd, "
91 "and 2 into group.\n"), noiselevel=-1)
92 writemsg(colorize("GOOD",
93 " portage:x:250:250:portage:/var/tmp/portage:/bin/false") \
94 + "\n", noiselevel=-1)
95 writemsg(colorize("GOOD", " portage::250:portage") + "\n",
97 portage_group_warning()
99 userpriv_groups = [portage_gid]
101 class _LazyUserprivGroups(portage.proxy.objectproxy.ObjectProxy):
102 def _get_target(self):
103 global userpriv_groups
104 if userpriv_groups is not self:
105 return userpriv_groups
106 userpriv_groups = _userpriv_groups
107 # Get a list of group IDs for the portage user. Do not use
108 # grp.getgrall() since it is known to trigger spurious
109 # SIGPIPE problems with nss_ldap.
110 mystatus, myoutput = \
111 portage.subprocess_getstatusoutput("id -G %s" % _portage_uname)
112 if mystatus == os.EX_OK:
113 for x in myoutput.split():
115 userpriv_groups.append(int(x))
118 userpriv_groups[:] = sorted(set(userpriv_groups))
119 return userpriv_groups
121 _userpriv_groups = userpriv_groups
122 userpriv_groups = _LazyUserprivGroups()