def run(self, *args):

        from yunohost.utils.ldap import _get_ldap_interface

        ldap = _get_ldap_interface()

        existing_perms_raw = ldap.search(
            "ou=permission,dc=yunohost,dc=org", "(objectclass=permissionYnh)", ["cn"]
        )
        existing_perms = [perm["cn"][0] for perm in existing_perms_raw]

        # Add SSH and SFTP permissions
        ldap_map = read_yaml(
            "/usr/share/yunohost/yunohost-config/moulinette/ldap_scheme.yml"
        )

        if "sftp.main" not in existing_perms:
            ldap.add(
                "cn=sftp.main,ou=permission",
                ldap_map["depends_children"]["cn=sftp.main,ou=permission"],
            )

        if "ssh.main" not in existing_perms:
            ldap.add(
                "cn=ssh.main,ou=permission",
                ldap_map["depends_children"]["cn=ssh.main,ou=permission"],
            )

            # Add a bash terminal to each users
            users = ldap.search(
                "ou=users,dc=yunohost,dc=org",
                filter="(loginShell=*)",
                attrs=["dn", "uid", "loginShell"],
            )
            for user in users:
                if user["loginShell"][0] == "/bin/false":
                    dn = user["dn"][0].replace(",dc=yunohost,dc=org", "")
                    ldap.update(dn, {"loginShell": ["/bin/bash"]})
                else:
                    user_permission_update(
                        "ssh.main", add=user["uid"][0], sync_perm=False
                    )

            permission_sync_to_user()

            # Somehow this is needed otherwise the PAM thing doesn't forget about the
            # old loginShell value ?
            subprocess.call(["nscd", "-i", "passwd"])

        if (
            "/etc/ssh/sshd_config" in manually_modified_files()
            and os.system(
                "grep -q '^ *AllowGroups\\|^ *AllowUsers' /etc/ssh/sshd_config"
            )
            != 0
        ):
            logger.error(m18n.n("diagnosis_sshd_config_insecure"))
Esempio n. 2
0
    def migrate_app_permission(app=None):
        logger.info(m18n.n("migration_0011_migrate_permission"))

        apps = _installed_apps()

        if app:
            if app not in apps:
                logger.error(
                    "Can't migrate permission for app %s because it ain't installed..."
                    % app
                )
                apps = []
            else:
                apps = [app]

        for app in apps:
            permission = app_setting(app, "allowed_users")
            path = app_setting(app, "path")
            domain = app_setting(app, "domain")

            url = "/" if domain and path else None
            if permission:
                known_users = list(user_list()["users"].keys())
                allowed = [
                    user for user in permission.split(",") if user in known_users
                ]
            else:
                allowed = ["all_users"]
            permission_create(
                app + ".main",
                url=url,
                allowed=allowed,
                show_tile=True,
                protected=False,
                sync_perm=False,
            )

            app_setting(app, "allowed_users", delete=True)

            # Migrate classic public app still using the legacy unprotected_uris
            if (
                app_setting(app, "unprotected_uris") == "/"
                or app_setting(app, "skipped_uris") == "/"
            ):
                user_permission_update(app + ".main", add="visitors", sync_perm=False)

        permission_sync_to_user()
Esempio n. 3
0
def user_group_delete(operation_logger,
                      groupname,
                      force=False,
                      sync_perm=True):
    """
    Delete user

    Keyword argument:
        groupname -- Groupname to delete

    """
    from yunohost.permission import permission_sync_to_user
    from yunohost.utils.ldap import _get_ldap_interface

    existing_groups = list(user_group_list()["groups"].keys())
    if groupname not in existing_groups:
        raise YunohostValidationError("group_unknown", group=groupname)

    # Refuse to delete primary groups of a user (e.g. group 'sam' related to user 'sam')
    # without the force option...
    #
    # We also can't delete "all_users" because that's a special group...
    existing_users = list(user_list()["users"].keys())
    undeletable_groups = existing_users + ["all_users", "visitors"]
    if groupname in undeletable_groups and not force:
        raise YunohostValidationError("group_cannot_be_deleted",
                                      group=groupname)

    operation_logger.start()
    ldap = _get_ldap_interface()
    try:
        ldap.remove("cn=%s,ou=groups" % groupname)
    except Exception as e:
        raise YunohostError("group_deletion_failed", group=groupname, error=e)

    if sync_perm:
        permission_sync_to_user()

    if groupname not in existing_users:
        logger.success(m18n.n("group_deleted", group=groupname))
    else:
        logger.debug(m18n.n("group_deleted", group=groupname))
Esempio n. 4
0
def user_group_update(operation_logger,
                      groupname,
                      add=None,
                      remove=None,
                      force=False,
                      sync_perm=True):
    """
    Update user informations

    Keyword argument:
        groupname -- Groupname to update
        add -- User(s) to add in group
        remove -- User(s) to remove in group

    """

    from yunohost.permission import permission_sync_to_user
    from yunohost.utils.ldap import _get_ldap_interface

    existing_users = list(user_list()['users'].keys())

    # Refuse to edit a primary group of a user (e.g. group 'sam' related to user 'sam')
    # Those kind of group should only ever contain the user (e.g. sam) and only this one.
    # We also can't edit "all_users" without the force option because that's a special group...
    if not force:
        if groupname == "all_users":
            raise YunohostError('group_cannot_edit_all_users')
        elif groupname == "visitors":
            raise YunohostError('group_cannot_edit_visitors')
        elif groupname in existing_users:
            raise YunohostError('group_cannot_edit_primary_group',
                                group=groupname)

    # We extract the uid for each member of the group to keep a simple flat list of members
    current_group = user_group_info(groupname)["members"]
    new_group = copy.copy(current_group)

    if add:
        users_to_add = [add] if not isinstance(add, list) else add

        for user in users_to_add:
            if user not in existing_users:
                raise YunohostError('user_unknown', user=user)

            if user in current_group:
                logger.warning(
                    m18n.n('group_user_already_in_group',
                           user=user,
                           group=groupname))
            else:
                operation_logger.related_to.append(('user', user))

        new_group += users_to_add

    if remove:
        users_to_remove = [remove] if not isinstance(remove, list) else remove

        for user in users_to_remove:
            if user not in current_group:
                logger.warning(
                    m18n.n('group_user_not_in_group',
                           user=user,
                           group=groupname))
            else:
                operation_logger.related_to.append(('user', user))

        # Remove users_to_remove from new_group
        # Kinda like a new_group -= users_to_remove
        new_group = [u for u in new_group if u not in users_to_remove]

    new_group_dns = [
        "uid=" + user + ",ou=users,dc=yunohost,dc=org" for user in new_group
    ]

    if set(new_group) != set(current_group):
        operation_logger.start()
        ldap = _get_ldap_interface()
        try:
            ldap.update('cn=%s,ou=groups' % groupname, {
                "member": set(new_group_dns),
                "memberUid": set(new_group)
            })
        except Exception as e:
            raise YunohostError('group_update_failed',
                                group=groupname,
                                error=e)

    if groupname != "all_users":
        logger.success(m18n.n('group_updated', group=groupname))
    else:
        logger.debug(m18n.n('group_updated', group=groupname))

    if sync_perm:
        permission_sync_to_user()
    return user_group_info(groupname)
Esempio n. 5
0
def user_group_create(operation_logger,
                      groupname,
                      gid=None,
                      primary_group=False,
                      sync_perm=True):
    """
    Create group

    Keyword argument:
        groupname -- Must be unique

    """
    from yunohost.permission import permission_sync_to_user
    from yunohost.utils.ldap import _get_ldap_interface

    ldap = _get_ldap_interface()

    # Validate uniqueness of groupname in LDAP
    conflict = ldap.get_conflict({'cn': groupname},
                                 base_dn='ou=groups,dc=yunohost,dc=org')
    if conflict:
        raise YunohostError('group_already_exist', group=groupname)

    # Validate uniqueness of groupname in system group
    all_existing_groupnames = {x.gr_name for x in grp.getgrall()}
    if groupname in all_existing_groupnames:
        if primary_group:
            logger.warning(
                m18n.n('group_already_exist_on_system_but_removing_it',
                       group=groupname))
            subprocess.check_call("sed --in-place '/^%s:/d' /etc/group" %
                                  groupname,
                                  shell=True)
        else:
            raise YunohostError('group_already_exist_on_system',
                                group=groupname)

    if not gid:
        # Get random GID
        all_gid = {x.gr_gid for x in grp.getgrall()}

        uid_guid_found = False
        while not uid_guid_found:
            gid = str(random.randint(200, 99999))
            uid_guid_found = gid not in all_gid

    attr_dict = {
        'objectClass': ['top', 'groupOfNamesYnh', 'posixGroup'],
        'cn': groupname,
        'gidNumber': gid,
    }

    # Here we handle the creation of a primary group
    # We want to initialize this group to contain the corresponding user
    # (then we won't be able to add/remove any user in this group)
    if primary_group:
        attr_dict["member"] = [
            "uid=" + groupname + ",ou=users,dc=yunohost,dc=org"
        ]

    operation_logger.start()
    try:
        ldap.add('cn=%s,ou=groups' % groupname, attr_dict)
    except Exception as e:
        raise YunohostError('group_creation_failed', group=groupname, error=e)

    if sync_perm:
        permission_sync_to_user()

    if not primary_group:
        logger.success(m18n.n('group_created', group=groupname))
    else:
        logger.debug(m18n.n('group_created', group=groupname))

    return {'name': groupname}
Esempio n. 6
0
def migrate_legacy_permission_settings(app=None):

    logger.info(m18n.n("migrating_legacy_permission_settings"))
    apps = _installed_apps()

    if app:
        if app not in apps:
            logger.error(
                "Can't migrate permission for app %s because it ain't installed..."
                % app)
            apps = []
        else:
            apps = [app]

    for app in apps:

        settings = _get_app_settings(app) or {}
        if settings.get("label"):
            user_permission_update(app + ".main",
                                   label=settings["label"],
                                   sync_perm=False)
            del settings["label"]

        def _setting(name):
            s = settings.get(name)
            return s.split(',') if s else []

        skipped_urls = [uri for uri in _setting('skipped_uris') if uri != '/']
        skipped_urls += ['re:' + regex for regex in _setting('skipped_regex')]
        unprotected_urls = [
            uri for uri in _setting('unprotected_uris') if uri != '/'
        ]
        unprotected_urls += [
            're:' + regex for regex in _setting('unprotected_regex')
        ]
        protected_urls = [
            uri for uri in _setting('protected_uris') if uri != '/'
        ]
        protected_urls += [
            're:' + regex for regex in _setting('protected_regex')
        ]

        if skipped_urls != []:
            permission_create(app + ".legacy_skipped_uris",
                              additional_urls=skipped_urls,
                              auth_header=False,
                              label=legacy_permission_label(app, "skipped"),
                              show_tile=False,
                              allowed='visitors',
                              protected=True,
                              sync_perm=False)
        if unprotected_urls != []:
            permission_create(app + ".legacy_unprotected_uris",
                              additional_urls=unprotected_urls,
                              auth_header=True,
                              label=legacy_permission_label(
                                  app, "unprotected"),
                              show_tile=False,
                              allowed='visitors',
                              protected=True,
                              sync_perm=False)
        if protected_urls != []:
            permission_create(app + ".legacy_protected_uris",
                              additional_urls=protected_urls,
                              auth_header=True,
                              label=legacy_permission_label(app, "protected"),
                              show_tile=False,
                              allowed=user_permission_list()['permissions'][
                                  app + ".main"]['allowed'],
                              protected=True,
                              sync_perm=False)

        legacy_permission_settings = [
            "skipped_uris", "unprotected_uris", "protected_uris",
            "skipped_regex", "unprotected_regex", "protected_regex"
        ]
        for key in legacy_permission_settings:
            if key in settings:
                del settings[key]

        _set_app_settings(app, settings)

        permission_sync_to_user()
Esempio n. 7
0
    def run(self, *args):

        from yunohost.utils.ldap import _get_ldap_interface

        ldap = _get_ldap_interface()

        existing_perms_raw = ldap.search("ou=permission,dc=yunohost,dc=org",
                                         "(objectclass=permissionYnh)", ["cn"])
        existing_perms = [perm["cn"][0] for perm in existing_perms_raw]

        # Add SSH and SFTP permissions
        if "sftp.main" not in existing_perms:
            ldap.add(
                "cn=sftp.main,ou=permission",
                {
                    "cn": "sftp.main",
                    "gidNumber": "5004",
                    "objectClass": ["posixGroup", "permissionYnh"],
                    "groupPermission": [],
                    "authHeader": "FALSE",
                    "label": "SFTP",
                    "showTile": "FALSE",
                    "isProtected": "TRUE",
                },
            )

        if "ssh.main" not in existing_perms:
            ldap.add(
                "cn=ssh.main,ou=permission",
                {
                    "cn": "ssh.main",
                    "gidNumber": "5003",
                    "objectClass": ["posixGroup", "permissionYnh"],
                    "groupPermission": [],
                    "authHeader": "FALSE",
                    "label": "SSH",
                    "showTile": "FALSE",
                    "isProtected": "TRUE",
                },
            )

            # Add a bash terminal to each users
            users = ldap.search(
                "ou=users,dc=yunohost,dc=org",
                filter="(loginShell=*)",
                attrs=["dn", "uid", "loginShell"],
            )
            for user in users:
                if user["loginShell"][0] == "/bin/false":
                    dn = user["dn"][0].replace(",dc=yunohost,dc=org", "")
                    ldap.update(dn, {"loginShell": ["/bin/bash"]})
                else:
                    user_permission_update("ssh.main",
                                           add=user["uid"][0],
                                           sync_perm=False)

            permission_sync_to_user()

            # Somehow this is needed otherwise the PAM thing doesn't forget about the
            # old loginShell value ?
            subprocess.call(["nscd", "-i", "passwd"])

        if ("/etc/ssh/sshd_config" in manually_modified_files() and os.system(
                "grep -q '^ *AllowGroups\\|^ *AllowUsers' /etc/ssh/sshd_config"
        ) != 0):
            logger.error(m18n.n("diagnosis_sshd_config_insecure"))