Пример #1
0
 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
Пример #2
0
 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
Пример #3
0
    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})
Пример #4
0
 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
Пример #5
0
 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)
Пример #6
0
    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)
Пример #7
0
 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
Пример #8
0
    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)
Пример #9
0
 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)
Пример #10
0
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
Пример #11
0
    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
Пример #12
0
    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
Пример #13
0
 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
Пример #14
0
    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
Пример #15
0
    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
        })
Пример #16
0
 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)