def umount(self): """Unmount partition.""" signals.emit("filesystems", "pre_umount", self) if not self.mountpoint: return s = libc.umount2(ctypes.c_char_p(b(self.mountpoint)), 0) if s == -1: excmsg = "Failed to unmount {0}: {1}" raise errors.OperationFailedError( excmsg.format(self.id, os.strerror(ctypes.get_errno()))) if self.crypt: crypto.luks_close(b(self.id)) signals.emit("filesystems", "post_umount", self) self.mountpoint = None
def mount(self, extra_opts={}): """Mount the NFS share.""" if not extra_opts: extra_opts = {"vers": "4"} opts = ",".join( ["{0}={1}".format(x, extra_opts[x]) for x in extra_opts] ) if not os.path.exists(self.path): os.makedirs(self.path) s = libc.mount(ctypes.c_char_p(b(self.network_path)), ctypes.c_char_p(b(self.path)), ctypes.c_char_p(b"nfs"), 0, ctypes.c_char_p(b(opts))) if s == -1: excmsg = "Failed to mount {0}: {1}" raise Exception(excmsg.format(self.id, os.strerror(ctypes.get_errno()))) else: self.is_mounted = True
def add(self, passwd): """ Add the user to LDAP. :param str passwd: user password to set """ try: ldif = conns.LDAP.search_s(self.ldap_id, ldap.SCOPE_BASE, "(objectClass=*)", None) msg = "A user named {0} already exists".format(self.name) raise errors.InvalidConfigError(msg) except ldap.NO_SUCH_OBJECT: pass # Create LDAP user with proper metadata ldif = { "objectClass": [b"mailAccount", b"inetOrgPerson", b"posixAccount"], "givenName": [b(self.first_name)], "sn": [b(self.last_name)] if self.last_name else [b"NONE"], "displayName": [b(self.full_name)], "cn": [b(self.full_name)], "uid": [b(self.name)], "mail": [b(self.name + "@" + self.domain)], "maildrop": [b(self.name)], "userPassword": [b(ldap_sha512_crypt.encrypt(passwd))], "gidNumber": [b"100"], "uidNumber": [b(str(self.uid))], "homeDirectory": [b("/home/" + self.name)], "loginShell": [b"/usr/bin/bash"] } ldif = ldap.modlist.addModlist(ldif) signals.emit("users", "pre_add", self) logger.debug("Roles", "Adding user: {0}".format(self.ldap_id)) conns.LDAP.add_s(self.ldap_id, ldif) modes = ["admin" if self.admin else "", "sudo" if self.sudo else ""] msg = "Setting user modes: {0}".format(", ".join(modes)) logger.debug("Roles", msg) self.update_adminsudo() self.update_samba(passwd) signals.emit("users", "post_add", {"user": self, "passwd": passwd})
def umount(self): """Unmount the Samba share.""" if not self.is_mounted: return s = libc.umount2(ctypes.c_char_p(b(self.path)), 0) if s == -1: excmsg = "Failed to unmount {0}: {1}" raise Exception(excmsg.format(self.id, os.strerror(ctypes.get_errno()))) else: self.is_mounted = False
def add(self): """Add the group to LDAP.""" try: ldif = conns.LDAP.search_s(self.ldap_id, ldap.SCOPE_SUBTREE, "(objectClass=*)", None) emsg = "A group with this name already exists" raise errors.InvalidConfigError(emsg) except ldap.NO_SUCH_OBJECT: pass ldif = { "objectClass": [b"posixGroup", b"top"], "cn": [b(self.name)], "gidNumber": [b(str(self.gid))] } if self.users: ldif["memberUid"] = [b(u) for u in self.users] ldif = ldap.modlist.addModlist(ldif) signals.emit("groups", "pre_add", self) conns.LDAP.add_s(self.ldap_id, ldif) signals.emit("groups", "post_add", self)
def update_adminsudo(self): """Update the user's admin and sudo group settings in LDAP.""" ldif = conns.LDAP.search_s( "cn=admins,ou=groups,{0}".format(self.rootdn), ldap.SCOPE_SUBTREE, "(objectClass=*)", None)[0][1] memlist = ldif["member"] ldif_vals = [(1, "member", None), (0, "member", memlist)] if self.admin and b(self.ldap_id) not in memlist: memlist += [b(self.ldap_id)] conns.LDAP.modify_s("cn=admins,ou=groups,{0}".format(self.rootdn), ldif_vals) elif not self.admin and self.ldap_id in memlist: memlist.remove(self.ldap_id) conns.LDAP.modify_s("cn=admins,ou=groups,{0}".format(self.rootdn), ldif_vals) try: conns.LDAP.search_s( "cn={0},ou=sudo,{1}".format(self.name, self.rootdn), ldap.SCOPE_SUBTREE, "(objectClass=*)", None) is_sudo = True except ldap.NO_SUCH_OBJECT: is_sudo = False if self.sudo and not is_sudo: nldif = { "objectClass": [b"sudoRole", b"top"], "cn": [b(self.name)], "sudoHost": b"ALL", "sudoCommand": b"ALL", "sudoUser": [b(self.name)], "sudoOption": b"authenticate" } nldif = ldap.modlist.addModlist(nldif) conns.LDAP.add_s("cn=" + self.name + ",ou=sudo," + self.rootdn, nldif) elif not self.sudo and is_sudo: conns.LDAP.delete_s("cn=" + self.name + ",ou=sudo," + self.rootdn)
def mount(self, extra_opts={}): """Mount the Samba share.""" if self.username and "user" not in extra_opts: extra_opts["user"] = self.username if self.password and "password" not in extra_opts: extra_opts["password"] = self.password opts = ",".join( ["{0}={1}".format(x, extra_opts[x]) for x in extra_opts] ) if self.readonly: opts = "ro" + ((","+opts) if opts else "") if not os.path.exists(self.path): os.makedirs(self.path) s = libc.mount(ctypes.c_char_p(b(self.network_path)), ctypes.c_char_p(b(self.path)), ctypes.c_char_p(b"cifs"), 0, ctypes.c_char_p(b(opts))) if s == -1: excmsg = "Failed to mount {0}: {1}" raise Exception(excmsg.format(self.id, os.strerror(ctypes.get_errno()))) else: self.is_mounted = True
def update(self): """Update a group object in LDAP. Change params on the object first.""" try: ldif = conns.LDAP.search_s(self.ldap_id, ldap.SCOPE_SUBTREE, "(objectClass=*)", None) except ldap.NO_SUCH_OBJECT: raise errors.InvalidConfigError("This group does not exist") ldif = ldap.modlist.modifyModlist( ldif[0][1], {"memberUid": [b(u) for u in self.users]}, ignore_oldexistent=1) signals.emit("groups", "pre_update", self) conns.LDAP.modify_s(self.ldap_id, ldif) signals.emit("groups", "post_update", self)
def add(self): """Add the domain to LDAP.""" try: ldif = conns.LDAP.search_s(self.ldap_id, ldap.SCOPE_SUBTREE, "(objectClass=*)", None) emsg = "This domain is already present here" raise errors.InvalidConfigError(emsg) except ldap.NO_SUCH_OBJECT: pass ldif = {"virtualdomain": [b(self.name)], "objectClass": [b"mailDomain", b"top"]} signals.emit("domains", "pre_add", self) conns.LDAP.add_s(self.ldap_id, ldap.modlist.addModlist(ldif)) signals.emit("domains", "post_add", self)
def get(uid=None, name=None): """ Get all LDAP users. :param str id: ID of single user to fetch :param str name: username of single user to fetch :returns: User(s) :rtype: User or list thereof """ r = [] rootdn = config.get("general", "ldap_rootdn") ldap_users = conns.LDAP.search_s("ou=users," + rootdn, ldap.SCOPE_SUBTREE, "(objectClass=inetOrgPerson)", None) for x in ldap_users: for y in x[1]: if y == "mail": continue if type(x[1][y]) == list and len(x[1][y]) == 1: x[1][y] = x[1][y][0] u = User(x[1]["uid"].decode(), x[1]["givenName"].decode(), x[1]["sn"].decode() if x[1]["sn"] != b"NONE" else None, int(x[1]["uidNumber"]), x[1]["mail"][0].split(b"@")[1].decode(), x[0].split("ou=users,")[1], [z.decode() for z in x[1]["mail"]]) # Check if the user is a member of the admin or sudo groups try: conns.LDAP.search_s("cn={0},ou=sudo,{1}".format(u.name, u.rootdn), ldap.SCOPE_SUBTREE, "(objectClass=*)", None) u.sudo = True except ldap.NO_SUCH_OBJECT: u.sudo = False memlist = conns.LDAP.search_s( "cn=admins,ou=groups,{0}".format(u.rootdn), ldap.SCOPE_SUBTREE, "(objectClass=*)", None)[0][1]["member"] if b("uid={0},ou=users,{1}".format(u.name, u.rootdn)) in memlist: u.admin = True else: u.admin = False if u.uid == uid: return u elif name and u.name == name: return u r.append(u) return r if uid is None and name is None else None
def verify_passwd(self, passwd): """ Validate the provided password against the hash stored in LDAP. :param str passwd: password to check """ try: c = ldap.initialize("ldap://localhost") c.simple_bind_s(self.ldap_id, passwd) data = c.search_s("cn=admins,ou=groups," + self.rootdn, ldap.SCOPE_SUBTREE, "(objectClass=*)", ["member"])[0][1]["member"] if b(self.ldap_id) not in data: return False return True except ldap.INVALID_CREDENTIALS: return False
def mount(self, passwd=None): """ Mount partition. :param str passwd: If disk is encrypted, use this passphrase to unlock """ if self.mountpoint and os.path.ismount(self.mountpoint): raise errors.InvalidConfigError("Virtual disk already mounted") signals.emit("filesystems", "pre_mount", self) if not os.path.isdir(os.path.join("/media", self.id)): os.makedirs(os.path.join("/media", self.id)) mount_point = self.mountpoint or os.path.join("/media", self.id) luks_point = os.path.join("/dev/mapper", self.id) # Find a free loopback device and mount loop = losetup.find_unused_loop_device() loop.mount(str(self.path), offset=1048576) if self.crypt and passwd: # If it's an encrypted virtual disk, decrypt first then mount s = crypto.luks_open(loop.device, self.id, passwd) if s != 0: loop.unmount() excmsg = "Failed to decrypt {0} with errno {1}" raise errors.OperationFailedError( excmsg.format(self.id, str(s))) s = libc.mount(ctypes.c_char_p(b(luks_point)), ctypes.c_char_p(b(mount_point)), ctypes.c_char_p(b(self.fstype)), 0, ctypes.c_char_p(b"")) if s == -1: crypto.luks_close(self.id) loop.unmount() excmsg = "Failed to mount {0}: {1}" raise errors.OperationFailedError( excmsg.format(self.id, os.strerror(ctypes.get_errno()))) elif self.crypt and not passwd: excstr = "Must provide password to decrypt encrypted container" raise errors.InvalidConfigError(excstr) else: s = libc.mount(ctypes.c_char_p(b(loop.device)), ctypes.c_char_p(b(mount_point)), ctypes.c_char_p(b(self.fstype)), 0, ctypes.c_char_p(b"")) if s == -1: loop.unmount() excstr = "Failed to mount {0}: {1}" raise errors.OperationFailedError( excmsg.format(self.id, os.strerror(ctypes.get_errno()))) signals.emit("filesystems", "post_mount", self) self.mountpoint = mount_point
def umount(self): """Unmount disk.""" if not self.mountpoint: return signals.emit("filesystems", "pre_umount", self) loops = losetup.get_loop_devices() for l in loops: if loops[l].is_used() and loops[l].get_filename() == self.path: dev = loops[l] break s = libc.umount2(ctypes.c_char_p(b(self.mountpoint)), 0) if s == -1: excmsg = "Failed to unmount {0}: {1}" raise errors.OperationFailedError( excmsg.format(self.id, os.strerror(ctypes.get_errno()))) if self.crypt: crypto.luks_close(self.id) if dev: dev.unmount() signals.emit("filesystems", "post_umount", self) self.mountpoint = None
def mount(self, passwd=None): """ Mount partition. :param str passwd: If disk is encrypted, use this passphrase to unlock """ if self.mountpoint and os.path.ismount(self.mountpoint): raise errors.InvalidConfigError("Disk partition already mounted") elif self.fstype == "Unknown": emsg = "Cannot mount a partition of unknown type" raise errors.InvalidConfigError(emsg) signals.emit("filesystems", "pre_mount", self) mount_point = self.mountpoint or os.path.join("/media", self.id) luks_point = os.path.join("/dev/mapper", self.id) if not os.path.isdir(mount_point): os.makedirs(mount_point) if self.crypt and passwd: # Decrypt the disk first if it's an encrypted disk s = crypto.luks_open(self.path, self.id, passwd) if s != 0: excmsg = "Failed to decrypt {0} with errno {1}" excmsg = excmsg.format(self.id, str(s)) raise errors.OperationFailedError(excmsg) s = libc.mount(ctypes.c_char_p(b(luks_point)), ctypes.c_char_p(b(mount_point)), ctypes.c_char_p(b(self.fstype)), 0, ctypes.c_char_p(b"")) if s == -1: crypto.luks_close(self.id) excmsg = "Failed to mount {0}: {1}" raise errors.OperationFailedError( excmsg.format(self.id, os.strerror(ctypes.get_errno()))) elif self.crypt and not passwd: emsg = "Must provide password to decrypt encrypted disk" raise errors.InvalidConfigError(emsg) else: s = libc.mount(ctypes.c_char_p(b(self.path)), ctypes.c_char_p(b(mount_point)), ctypes.c_char_p(b(self.fstype)), 0, ctypes.c_char_p(b"")) if s == -1: excmsg = "Failed to mount {0}: {1}" raise errors.OperationFailedError( excmsg.format(self.id, os.strerror(ctypes.get_errno()))) signals.emit("filesystems", "post_mount", self) self.mountpoint = mount_point
def update(self, newpasswd=""): """ Update a user's object in LDAP. Change params on the object first. To change password, do so via the ``newpasswd`` param here. :param str newpasswd: new password to set """ try: ldif = conns.LDAP.search_s(self.ldap_id, ldap.SCOPE_SUBTREE, "(objectClass=*)", None) except ldap.NO_SUCH_OBJECT: raise errors.InvalidConfigError("Users", "This user does not exist") self.mail = list(set(self.mail)) for i, x in enumerate(self.mail): if not x.endswith(self.domain): self.mail[i] = x.split("@")[0] + "@" + self.domain ldif = ldif[0][1] attrs = { "givenName": [b(self.first_name)], "sn": [b(self.last_name)] if self.last_name else [b"NONE"], "displayName": [b(self.full_name)], "cn": [b(self.full_name)], "mail": [b(x) for x in self.mail] } if newpasswd: attrs["userPassword"] = [b(ldap_sha512_crypt.encrypt(newpasswd))] signals.emit("users", "pre_update", self) nldif = ldap.modlist.modifyModlist(ldif, attrs, ignore_oldexistent=1) conns.LDAP.modify_s(self.ldap_id, nldif) self.update_adminsudo() self.update_samba(newpasswd) signals.emit("users", "post_update", { "user": self, "passwd": newpasswd })
def update_samba(self, passwd=""): """Update Samba values in LDAP.""" try: domain = conns.LDAP.search_s(self.rootdn, ldap.SCOPE_SUBTREE, "objectClass=sambaDomain", None) except ldap.NO_SUCH_OBJECT: domain = None if not domain: hostname = sysconfig.get_hostname().upper() sambaSID = "S-1-5-21-0-0-0" dldif = { "objectClass": [b"sambaDomain"], "sambaDomainName": [b(hostname)], "sambaSID": [b(sambaSID)], "sambaAlgorithmicRidBase": [b"1000"], "sambaNextUserRid": [b"1000"], "sambaMinPwdLength": [b"5"], "sambaPwdHistoryLength": [b"0"], "sambaLogonToChgPwd": [b"0"], "sambaMaxPwdAge": [b"-1"], "sambaMinPwdAge": [b"0"], "sambaLockoutDuration": [b"30"], "sambaLockoutObservationWindow": [b"30"], "sambaLockoutThreshold": [b"0"], "sambaForceLogoff": [b"-1"], "sambaRefuseMachinePwdChange": [b"0"], "sambaNextRid": [b(str(get_next_uid()))] } dldif = ldap.modlist.addModlist(dldif) try: conns.LDAP.add_s( "sambaDomainName={0},{1}".format(hostname, self.rootdn), dldif) except ldap.ALREADY_EXISTS: pass else: sambaSID = domain[0][1]["sambaSID"][0].decode() attrs = {"sambaNextRid": [b(str(get_next_uid()))]} dldif = ldap.modlist.modifyModlist(domain[0][1], attrs, ignore_oldexistent=1) conns.LDAP.modify_s(domain[0][0], dldif) if passwd: try: uldif = conns.LDAP.search_s(self.ldap_id, ldap.SCOPE_SUBTREE, "(objectClass=*)", None) except ldap.NO_SUCH_OBJECT: raise errors.InvalidConfigError("Users", "This user does not exist") uldif = uldif[0][1] attrs = { "objectClass": [ b"mailAccount", b"inetOrgPerson", b"posixAccount", b"sambaSamAccount" ], "sambaSID": [b("{0}-{1}".format(sambaSID, self.uid))], "sambaAcctFlags": [b"[UX ]"], "sambaNTPassword": [b(nthash.encrypt(passwd).upper())] } nldif = ldap.modlist.modifyModlist(uldif, attrs, ignore_oldexistent=1) conns.LDAP.modify_s(self.ldap_id, nldif)