Univention Bugzilla – Attachment 6990 Details for
Bug 38796
ensure uidNumber and gidNumber do not collide when add/mod user or group
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
"v2"
change_colliding-gids.py (text/x-python), 11.16 KB, created by
Daniel Tröder
on 2015-07-01 15:33:18 CEST
(
hide
)
Description:
"v2"
Filename:
MIME Type:
Creator:
Daniel Tröder
Created:
2015-07-01 15:33:18 CEST
Size:
11.16 KB
patch
obsolete
>#!/usr/bin/python ># ># Copyright 2015 Univention GmbH ># ># http://www.univention.de/ ># ># All rights reserved. ># ># The source code of this program is made available ># under the terms of the GNU Affero General Public License version 3 ># (GNU AGPL V3) as published by the Free Software Foundation. ># ># Binary versions of this program provided by Univention to you as ># well as other copyrighted, protected or trademarked materials like ># Logos, graphics, fonts, specific documentations and configurations, ># cryptographic keys etc. are subject to a license agreement between ># you and Univention and not subject to the GNU AGPL V3. ># ># In the case you use this program under the terms of the GNU AGPL V3, ># the program is provided in the hope that it will be useful, ># but WITHOUT ANY WARRANTY; without even the implied warranty of ># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ># GNU Affero General Public License for more details. ># ># You should have received a copy of the GNU Affero General Public ># License with the Debian GNU/Linux or Univention distribution in file ># /usr/share/common-licenses/AGPL-3; if not, see ># <http://www.gnu.org/licenses/>. > >import os >import sys >from optparse import OptionParser >import traceback >import datetime > >import univention.admin >import univention.admin.uldap >import univention.admin.config >import univention.admin.modules >import univention.admin.allocators as ualloc >from univention.config_registry import ConfigRegistry, handler_set, handler_unset > >grp_blacklist = ["root", "daemon", "bin", "sys", "adm", "tty", "disk", "lp", "mail", "news", "uucp", "man", "proxy", > "kmem", "dialout", "fax", "voice", "cdrom", "floppy", "tape", "sudo", "audio", "dip", "www-data", > "backup", "operator", "list", "irc", "src", "gnats", "shadow", "utmp", "video", "sasl", "plugdev", > "staff", "games", "users", "nogroup", "libuuid", "crontab", "tss", "scanner", "nvram", "rdma", "fuse", > "kvm", "ssh", "apt-mirror", "ssl-cert", "postfix", "postdrop", "openldap", "nagios", "ntp", "bind", > "utempter", "sambashare", "winbindd_priv", "Domain Admins", "Domain Guests", > "Windows Hosts", "DC Backup Hosts", "DC Slave", "Hosts", "Computers", "Printer-Admins", > "Backup Join", "Slave Join", "Authenticated Users", "World Authority", "Everyone", > "Null Authority", "Nobody", "Enterprise Domain Controllers", "Remote Interactive Logon", > "SChannel Authentication", "Digest Authentication", "Terminal Server User", > "NTLM Authentication", "Other Organization", "This Organization", "Anonymous Logon", "Network Service", > "Creator Group", "Creator Owner", "Local Service", "Owner Rights", > "Interactive", "Restricted", "Network", "Service", "Dialup", "System", "Batch", "Proxy", "IUSR", > "Self", "Performance Log Users", "DnsUpdateProxy", "Cryptographic Operators", "Schema Admins", > "Backup Operators", "Administrators", "Domain Computers", "Windows Authorization Access Group", > "IIS_IUSRS", "RAS and IAS Servers", "Network Configuration Operators", "Account Operators", > "Distributed COM Users", "Read-Only Domain Controllers", "Terminal Server License Servers", > "Replicator", "Allowed RODC Password Replication Group", "Denied RODC Password Replication Group", > "Guests", "Users", "Enterprise Admins", "Group Policy Creator Owners", "Server Operators", > "Domain Controllers", "DnsAdmins", "Cert Publishers", "Incoming Forest Trust Builders", > "Event Log Readers", "Pre-Windows 2000 Compatible Access", "Remote Desktop Users", > "Performance Monitor Users", "Certificate Service DCOM Access", > "Enterprise Read-Only Domain Controllers"] > >user_blacklist = ["Administrator", "krbtgt"] > > >univention.admin.modules.update() >univention.admin.syntax.update_choices() >lo, position = univention.admin.uldap.getAdminConnection() >co = univention.admin.config.config() >group_module = univention.admin.modules.get('groups/group') >user_module = univention.admin.modules.get('users/user') > > >def collect_gids(): > users = dict() > for dn, attrs in lo.search('(&(uidNumber=*)(objectClass=posixAccount))', attr=('uidNumber', )): > xid = attrs.get('uidNumber') > if xid: > users[(int(xid[0]))] = dn > groups = dict() > for dn, attrs in lo.search('(&(gidNumber=*)(objectClass=posixGroup))', attr=('gidNumber', )): > xid = attrs.get('gidNumber') > if xid: > groups[(int(xid[0]))] = dn > > common_ids = set(users.keys()).intersection(set(groups.keys())) > > if options.verbose: > print "# uidNumbers: %r" % users.keys() > print "# gidNumbers: %r" % groups.keys() > print "# common ids: %r" % common_ids > > res = list() > for cid in common_ids: > new_gidNumber = int(cid) > while new_gidNumber in groups or new_gidNumber in users: > new_gidNumber = int(ualloc.request(lo, position, 'gidNumber')) > res.append((cid, new_gidNumber)) > return res > >def write_gids(gids, filename): > with open(filename, "w") as f: > f.writelines(["%d %d\n" % gid for gid in gids]) > >def read_gids(filename): > res = list() > with open(filename, "r") as f: > for line in f: > try: > from_gid, to_gid = line.strip().split() > res.append((int(from_gid), int(to_gid))) > if options.verbose: > print "# %r -> %r" % (from_gid, to_gid) > except IndexError: > pass > except ValueError: > pass > return res > >def change_users_primary_groups(from_gid, to_gid, from_group): > users = univention.admin.modules.lookup(user_module, co, lo, scope='sub', superordinate=None, filter="(gidNumber=%d)" % from_gid) > bl = 0 > for user in users: > if user["username"] in user_blacklist: > err_file.write("USERPRIMGRPSET NOT changing blicklisted user %r from group %r to %r\n" % (user["username"], from_gid, to_gid)) > bl += 1 > else: > err_file.write("USERPRIMGRPSET %r : %r -> %r\n" % (user["username"], from_gid, to_gid)) > user.open() > user["primaryGroup"] = from_group.dn > user.modify() > return len(users) - bl > >def change_gids(gids): > for from_gid, to_gid in gids: > try: > from_group = univention.admin.modules.lookup(group_module, co, lo, scope='sub', superordinate=None, filter='(gidNumber=%d)' % from_gid) > if len(from_group) == 1: > from_group = from_group[0] > if options.verbose: > print "# %r -> %r (%r)" % (from_gid, to_gid, from_group['name']) > if from_group["name"] in grp_blacklist: > print " not changing blacklisted group %s." % from_group["name"] > continue > from_group.open() > from_group.descriptions["gidNumber"].may_change = 1 > from_group['gidNumber'] = str(to_gid) > from_group.descriptions["gidNumber"].may_change = 0 > from_group.modify() > users_changed = change_users_primary_groups(from_gid, to_gid, from_group) > print " %r users primary group changed." % users_changed > except: > print "Error changing %r -> %r, writing traceback to %s." % (from_gid, to_gid, err_file_name) > err_file.write("GRPSET %r -> %r\n" % (from_gid, to_gid)) > err_file.write(traceback.format_exc()) > err_file.write("\n") > >def walk_error(oserror): > print "Error reading directory, writing traceback to %s." % err_file_name > err_file.write("LIST %r\n" % oserror) > >def chgrp(filepath, gid): > uid = os.stat(filepath).st_uid > os.chown(filepath, uid, gid) > >def get_users_in_blacklisted_groups(): > users = dict() > for groupname in grp_blacklist: > group = univention.admin.modules.lookup(group_module, co, lo, scope='sub', superordinate=None, filter='(name=%s)' % groupname) > if len(group) == 1: > _users = univention.admin.modules.lookup(user_module, co, lo, scope='sub', superordinate=None, filter="(gidNumber=%s)" % group[0]["gidNumber"]) > for u in _users: > try: > users["%s (%s)" % (u["username"], u["uidNumber"])] += ", %s (%s)" %(groupname, group[0]["gidNumber"]) > except KeyError: > users["%s (%s)" % (u["username"], u["uidNumber"])] = "%s (%s)" %(groupname, group[0]["gidNumber"]) > return users > >parser = OptionParser() >parser.add_option("-b", "--blacklists", action="store_true", help="print blacklisted users and groups and exit [default=off].") >parser.add_option("-d", "--dir", dest="chgrp_directory", > help="run chgrp recursivly on directory, expects change information from file with -i", > metavar="FILE") >parser.add_option("-i", "--infile", dest="in_filename", help="read group changes from FILE", metavar="FILE") >parser.add_option("-o", "--outfile", dest="out_filename", help="write group changes to FILE", metavar="FILE") >parser.add_option("-l", "--ldap", action="store_true", help="Modify GIDs of groups in LDAP, expects change information from file with -i [default=off].") >parser.add_option("-v", "--verbose", action="store_false", dest="verbose", default=True, > help="write about current action [default=on].") > >(options, args) = parser.parse_args() > >if options.blacklists: > print "User blacklist: %r\n" % user_blacklist > print "Group blacklist: %r\n" % grp_blacklist > print "Users with a blacklisted primary group: %r" % get_users_in_blacklisted_groups() > sys.exit(0) >if options.chgrp_directory and not options.in_filename: > parser.error("Please supply the directory that run chgrp should be run on recursivly with '-i'.") >if options.in_filename and options.out_filename: > parser.error("Options -i and -o are mutually exclusive.") >if not options.in_filename and not options.out_filename and not options.blacklists: > parser.error("Please use either -b, -i or -o.") >if options.in_filename and not (options.chgrp_directory or options.ldap): > parser.error("Please use -i with -d or -l.") >if options.ldap and not options.in_filename: > parser.error("Please supply data to change the group information in LDAP with '-i'.") >if options.ldap and options.out_filename: > parser.error("Options -l and -o are mutually exclusive.") > >try: > os.mkdir("/var/log/changegrp/") >except OSError: > pass >err_file_name = "/var/log/changegrp/%s.log" % datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S") >err_file = open(err_file_name, "ab") > >if options.out_filename: > gids = collect_gids() > write_gids(gids, options.out_filename) > print "Wrote %d GID pairs to %s." % (len(gids), options.out_filename) > err_file.close() > sys.exit(0) > >if options.in_filename: > print "Reading list of groups from %r..." % options.in_filename > > gids = read_gids(options.in_filename) > print "... read %d GID pairs." % len(gids) > > if options.ldap: > print "Changing %d gidNumbers in LDAP..." % len(gids) > change_gids(gids) > print "... done." > err_file.close() > sys.exit(0) > > if options.chgrp_directory: > gids_dict = dict(gids) > stats = {"dir": 0, "file": 0} > print "Running chgrp recursivly on %r..." % options.chgrp_directory > for root, dirs, files in os.walk(options.chgrp_directory, onerror=walk_error): > print "# %r..." % root > for _dir in dirs: > dir_gid = os.stat(os.path.join(root, _dir)).st_gid > if dir_gid in gids_dict: > stats["dir"] += 1 > chgrp(os.path.join(root, _dir), gids_dict[dir_gid]) > if options.verbose: > err_file.write("CHGRP %r: %r -> %r\n" % (os.path.join(root, _dir), dir_gid, gids_dict[dir_gid])) > for _file in files: > file_gid = os.stat(os.path.join(root, _file)).st_gid > if file_gid in gids_dict: > stats["file"] += 1 > chgrp(os.path.join(root, _file), gids_dict[file_gid]) > if options.verbose: > err_file.write("CHGRP %r: %r -> %r\n" % (os.path.join(root, _file), file_gid, gids_dict[file_gid])) > print "... done. Changed permissions on %d directories and %d files." % (stats["dir"], stats["file"]) > err_file.close() > sys.exit(0)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 38796
:
6987
| 6990