##// END OF EJS Templates
Only read .hg/hgrc files from trusted users/groups...
Alexis S. L. Carvalho -
r3013:494521a3 default
parent child Browse files
Show More
@@ -0,0 +1,112 b''
1 #!/usr/bin/env python
2 # Since it's not easy to write a test that portably deals
3 # with files from different users/groups, we cheat a bit by
4 # monkey-patching some functions in the util module
5
6 import os
7 from mercurial import ui, util
8
9 hgrc = os.environ['HGRCPATH']
10
11 def testui(user='foo', group='bar', tusers=(), tgroups=(),
12 cuser='foo', cgroup='bar'):
13 # user, group => owners of the file
14 # tusers, tgroups => trusted users/groups
15 # cuser, cgroup => user/group of the current process
16
17 # write a global hgrc with the list of trusted users/groups and
18 # some setting so that we can be sure it was read
19 f = open(hgrc, 'w')
20 f.write('[paths]\n')
21 f.write('global = /some/path\n\n')
22
23 if tusers or tgroups:
24 f.write('[trusted]\n')
25 if tusers:
26 f.write('users = %s\n' % ', '.join(tusers))
27 if tgroups:
28 f.write('groups = %s\n' % ', '.join(tgroups))
29 f.close()
30
31 # override the functions that give names to uids and gids
32 def username(uid=None):
33 if uid is None:
34 return cuser
35 return user
36 util.username = username
37
38 def groupname(gid=None):
39 if gid is None:
40 return 'bar'
41 return group
42 util.groupname = groupname
43
44 # try to read everything
45 #print '# File belongs to user %s, group %s' % (user, group)
46 #print '# trusted users = %s; trusted groups = %s' % (tusers, tgroups)
47 kind = ('different', 'same')
48 who = ('', 'user', 'group', 'user and the group')
49 trusted = who[(user in tusers) + 2*(group in tgroups)]
50 if trusted:
51 trusted = ', but we trust the ' + trusted
52 print '# %s user, %s group%s' % (kind[user == cuser], kind[group == cgroup],
53 trusted)
54
55 parentui = ui.ui()
56 u = ui.ui(parentui=parentui)
57 u.readconfig('.hg/hgrc')
58 for name, path in u.configitems('paths'):
59 print name, '=', path
60 print
61
62 return u
63
64 os.mkdir('repo')
65 os.chdir('repo')
66 os.mkdir('.hg')
67 f = open('.hg/hgrc', 'w')
68 f.write('[paths]\n')
69 f.write('local = /another/path\n\n')
70 f.close()
71
72 #print '# Everything is run by user foo, group bar\n'
73
74 # same user, same group
75 testui()
76 # same user, different group
77 testui(group='def')
78 # different user, same group
79 testui(user='abc')
80 # ... but we trust the group
81 testui(user='abc', tgroups=['bar'])
82 # different user, different group
83 testui(user='abc', group='def')
84 # ... but we trust the user
85 testui(user='abc', group='def', tusers=['abc'])
86 # ... but we trust the group
87 testui(user='abc', group='def', tgroups=['def'])
88 # ... but we trust the user and the group
89 testui(user='abc', group='def', tusers=['abc'], tgroups=['def'])
90 # ... but we trust all users
91 print '# we trust all users'
92 testui(user='abc', group='def', tusers=['*'])
93 # ... but we trust all groups
94 print '# we trust all groups'
95 testui(user='abc', group='def', tgroups=['*'])
96 # ... but we trust the whole universe
97 print '# we trust all users and groups'
98 testui(user='abc', group='def', tusers=['*'], tgroups=['*'])
99 # ... check that users and groups are in different namespaces
100 print "# we don't get confused by users and groups with the same name"
101 testui(user='abc', group='def', tusers=['def'], tgroups=['abc'])
102 # ... lists of user names work
103 print "# list of user names"
104 testui(user='abc', group='def', tusers=['foo', 'xyz', 'abc', 'bleh'],
105 tgroups=['bar', 'baz', 'qux'])
106 # ... lists of group names work
107 print "# list of group names"
108 testui(user='abc', group='def', tusers=['foo', 'xyz', 'bleh'],
109 tgroups=['bar', 'def', 'baz', 'qux'])
110
111 print "# Can't figure out the name of the user running this process"
112 testui(user='abc', group='def', cuser=None)
@@ -0,0 +1,67 b''
1 # same user, same group
2 global = /some/path
3 local = /another/path
4
5 # same user, different group
6 global = /some/path
7 local = /another/path
8
9 # different user, same group
10 not reading file .hg/hgrc from untrusted user abc, group bar
11 global = /some/path
12
13 # different user, same group, but we trust the group
14 global = /some/path
15 local = /another/path
16
17 # different user, different group
18 not reading file .hg/hgrc from untrusted user abc, group def
19 global = /some/path
20
21 # different user, different group, but we trust the user
22 global = /some/path
23 local = /another/path
24
25 # different user, different group, but we trust the group
26 global = /some/path
27 local = /another/path
28
29 # different user, different group, but we trust the user and the group
30 global = /some/path
31 local = /another/path
32
33 # we trust all users
34 # different user, different group
35 global = /some/path
36 local = /another/path
37
38 # we trust all groups
39 # different user, different group
40 global = /some/path
41 local = /another/path
42
43 # we trust all users and groups
44 # different user, different group
45 global = /some/path
46 local = /another/path
47
48 # we don't get confused by users and groups with the same name
49 # different user, different group
50 not reading file .hg/hgrc from untrusted user abc, group def
51 global = /some/path
52
53 # list of user names
54 # different user, different group, but we trust the user
55 global = /some/path
56 local = /another/path
57
58 # list of group names
59 # different user, different group, but we trust the group
60 global = /some/path
61 local = /another/path
62
63 # Can't figure out the name of the user running this process
64 # different user, different group
65 global = /some/path
66 local = /another/path
67
@@ -50,6 +50,8 b' installed.'
50 50 particular repository. This file is not version-controlled, and
51 51 will not get transferred during a "clone" operation. Options in
52 52 this file override options in all other configuration files.
53 On Unix, this file is only read if it belongs to a trusted user
54 or to a trusted group.
53 55
54 56 SYNTAX
55 57 ------
@@ -349,6 +351,16 b' server::'
349 351 6Mbps), uncompressed streaming is slower, because of the extra
350 352 data transfer overhead. Default is False.
351 353
354 trusted::
355 Mercurial will only read the .hg/hgrc file from a repository if
356 it belongs to a trusted user or to a trusted group. This section
357 specifies what users and groups are trusted. To trust everybody,
358 list a user or a group with name "*".
359 users;;
360 Comma-separated list of trusted users.
361 groups;;
362 Comma-separated list of trusted groups.
363
352 364 ui::
353 365 User interface controls.
354 366 debug;;
@@ -19,6 +19,8 b' class ui(object):'
19 19 # this is the parent of all ui children
20 20 self.parentui = None
21 21 self.readhooks = list(readhooks)
22 self.trusted_users = {}
23 self.trusted_groups = {}
22 24 self.cdata = ConfigParser.SafeConfigParser()
23 25 self.readconfig(util.rcpath())
24 26
@@ -37,6 +39,8 b' class ui(object):'
37 39 # parentui may point to an ui object which is already a child
38 40 self.parentui = parentui.parentui or parentui
39 41 self.readhooks = list(parentui.readhooks or readhooks)
42 self.trusted_users = parentui.trusted_users.copy()
43 self.trusted_groups = parentui.trusted_groups.copy()
40 44 parent_cdata = self.parentui.cdata
41 45 self.cdata = ConfigParser.SafeConfigParser(parent_cdata.defaults())
42 46 # make interpolation work
@@ -72,7 +76,22 b' class ui(object):'
72 76 fn = [fn]
73 77 for f in fn:
74 78 try:
75 self.cdata.read(f)
79 fp = open(f)
80 except IOError:
81 continue
82 if ((self.trusted_users or self.trusted_groups) and
83 '*' not in self.trusted_users and
84 '*' not in self.trusted_groups):
85 st = util.fstat(fp)
86 user = util.username(st.st_uid)
87 group = util.groupname(st.st_gid)
88 if (user not in self.trusted_users and
89 group not in self.trusted_groups):
90 self.warn(_('not reading file %s from untrusted '
91 'user %s, group %s\n') % (f, user, group))
92 continue
93 try:
94 self.cdata.readfp(fp, f)
76 95 except ConfigParser.ParsingError, inst:
77 96 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
78 97 # translate paths relative to root (or home) into absolute paths
@@ -81,6 +100,13 b' class ui(object):'
81 100 for name, path in self.configitems("paths"):
82 101 if path and "://" not in path and not os.path.isabs(path):
83 102 self.cdata.set("paths", name, os.path.join(root, path))
103 user = util.username()
104 if user is not None:
105 self.trusted_users[user] = 1
106 for user in self.configlist('trusted', 'users'):
107 self.trusted_users[user] = 1
108 for group in self.configlist('trusted', 'groups'):
109 self.trusted_groups[group] = 1
84 110 for hook in self.readhooks:
85 111 hook(self)
86 112
@@ -15,7 +15,7 b' platform-specific details from the core.'
15 15 from i18n import gettext as _
16 16 from demandload import *
17 17 demandload(globals(), "cStringIO errno getpass popen2 re shutil sys tempfile")
18 demandload(globals(), "os threading time")
18 demandload(globals(), "os threading time pwd grp")
19 19
20 20 # used by parsedate
21 21 defaultdateformats = ('%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M',
@@ -509,6 +509,38 b' def getuser():'
509 509 raise Abort(_('user name not available - set USERNAME '
510 510 'environment variable'))
511 511
512 def username(uid=None):
513 """Return the name of the user with the given uid.
514
515 If uid is None, return the name of the current user."""
516 try:
517 # force an ImportError if there's no module pwd
518 getpwuid = pwd.getpwuid
519 if uid is None:
520 uid = os.getuid()
521 try:
522 return getpwuid(uid)[0]
523 except KeyError:
524 return str(uid)
525 except ImportError:
526 return None
527
528 def groupname(gid=None):
529 """Return the name of the group with the given gid.
530
531 If gid is None, return the name of the current group."""
532 try:
533 # force an ImportError if there's no module grp
534 getgrgid = grp.getgrgid
535 if gid is None:
536 gid = os.getgid()
537 try:
538 return getgrgid(gid)[0]
539 except KeyError:
540 return str(gid)
541 except ImportError:
542 return None
543
512 544 # Platform specific variants
513 545 if os.name == 'nt':
514 546 demandload(globals(), "msvcrt")
General Comments 0
You need to be logged in to leave comments. Login now