def delete_advisory(advisory_id):
    advisory, pkg, group = (db.session.query(Advisory, CVEGroupPackage, CVEGroup)
                            .filter(Advisory.id == advisory_id)
                            .join(CVEGroupPackage).join(CVEGroup)).first()

    if not advisory:
        return not_found()

    if Publication.scheduled != advisory.publication:
        return forbidden()

    form = ConfirmForm()
    title = 'Delete {}'.format(advisory.id)
    if not form.validate_on_submit():
        return render_template('form/delete_advisory.html',
                               title=title,
                               heading=title,
                               form=form,
                               advisory=advisory,
                               pkg=pkg,
                               group=group)

    if not form.confirm.data:
        return redirect('/{}'.format(advisory.id))

    db.session.delete(advisory)
    db.session.commit()
    flash('Deleted {}'.format(advisory.id))
    return redirect('/')
def delete_user(username):
    user = User.query.filter_by(name=username).first()
    if not user:
        return not_found()

    form = ConfirmForm()
    title = 'Delete {}'.format(username)
    if not form.validate_on_submit():
        return render_template('admin/form/delete_user.html',
                               title=title,
                               heading=title,
                               form=form,
                               user=user)

    if not form.confirm.data:
        return redirect('/user')

    active_admins = User.query.filter_by(active=True, role=UserRole.administrator).count()
    if user.id == current_user.id and 1 >= active_admins:
        return forbidden()

    user_invalidate(user)
    db.session.delete(user)
    db.session.commit()
    flash('Deleted user {}'.format(user.name))
    return redirect('/user')
def edit_user(username):
    own_user = username == current_user.name
    if not current_user.role.is_administrator and not own_user:
        forbidden()

    user = User.query.filter_by(name=username).first()
    if not user:
        return not_found()

    form = UserForm(edit=True)
    if not form.is_submitted():
        form.username.data = user.name
        form.email.data = user.email
        form.role.data = user.role.name
        form.active.data = user.active
    if not form.validate_on_submit():
        return render_template('admin/form/user.html',
                               title='Edit {}'.format(username),
                               form=form,
                               User=User,
                               random_password=True,
                               password_length={'min': TRACKER_PASSWORD_LENGTH_MIN,
                                                'max': TRACKER_PASSWORD_LENGTH_MAX})

    active_admins = User.query.filter_by(active=True, role=UserRole.administrator).count()
    if user.id == current_user.id and 1 == active_admins and not form.active.data:
        return forbidden()

    user.name = form.username.data
    user.email = form.email.data
    user.role = UserRole.fromstring(form.role.data)
    if form.random_password.data:
        form.password.data = random_string()
    if 0 != len(form.password.data):
        user.salt = random_string()
        user.password = hash_password(form.password.data, user.salt)
    user.active = form.active.data
    user_invalidate(user)
    db.session.commit()

    flash_password = ''
    if form.random_password.data:
        flash_password = '******'.format(form.password.data)
    flash('Edited user {}{}'.format(user.name, flash_password))
    return redirect('/user')
def delete_group(avg):
    avg_id = avg.replace('AVG-', '')
    entries = (db.session.query(CVEGroup, CVE, CVEGroupPackage, Advisory)
               .filter(CVEGroup.id == avg_id)
               .join(CVEGroupEntry).join(CVE).join(CVEGroupPackage)
               .outerjoin(Advisory, Advisory.group_package_id == CVEGroupPackage.id)
               ).all()
    if not entries:
        return not_found()

    group = entries[0][0]
    issues = set()
    packages = set()
    advisories = set()
    for group, issue, pkg, advisory in entries:
        issues.add(issue)
        packages.add(pkg)
        if advisory:
            advisories.add(advisory)

    if not user_can_delete_group(advisories):
        return forbidden()

    issues = sorted(issues, key=lambda item: item.id)
    packages = sorted(packages, key=lambda item: item.pkgname)
    advisories = sorted(advisories, key=lambda item: item.id, reverse=True)

    form = ConfirmForm()
    title = 'Delete {}'.format(avg)
    if not form.validate_on_submit():
        return render_template('form/delete_group.html',
                               title=title,
                               heading=title,
                               form=form,
                               group=group,
                               issues=issues,
                               packages=packages)

    if not form.confirm.data:
        return redirect('/{}'.format(group))

    db.session.delete(group)
    db.session.commit()
    flash('Deleted {}'.format(group))
    return redirect('/')
def edit_cve(cve):
    entries = (db.session.query(
        CVE, CVEGroup,
        Advisory).filter(CVE.id == cve).outerjoin(CVEGroupEntry).outerjoin(
            CVEGroup).outerjoin(CVEGroupPackage).outerjoin(
                Advisory,
                Advisory.group_package_id == CVEGroupPackage.id)).all()
    if not entries:
        return not_found()

    cve = entries[0][0]
    groups = set(group for (cve, group, advisory) in entries if group)
    advisories = set(advisory for (cve, group, advisory) in entries
                     if advisory)

    if not user_can_edit_issue(advisories):
        return forbidden()

    form = CVEForm(edit=True)
    if not form.is_submitted():
        form.cve.data = cve.id
        form.issue_type.data = cve.issue_type
        form.description.data = cve.description
        form.severity.data = cve.severity.name
        form.remote.data = cve.remote.name
        form.reference.data = cve.reference
        form.notes.data = cve.notes
    if not form.validate_on_submit():
        if advisories:
            flash(
                'WARNING: This is referenced by an already published advisory!',
                'warning')
        return render_template('form/cve.html',
                               title='Edit {}'.format(cve),
                               form=form,
                               CVE=CVE)

    severity = Severity.fromstring(form.severity.data)
    severity_changed = cve.severity != severity
    issue_type_changed = cve.issue_type != form.issue_type.data

    cve.issue_type = form.issue_type.data
    cve.description = form.description.data
    cve.severity = severity
    cve.remote = Remote.fromstring(form.remote.data)
    cve.reference = form.reference.data
    cve.notes = form.notes.data

    if severity_changed or issue_type_changed:
        # update cached group severity for all goups containing this issue
        group_ids = [group.id for group in groups]
        issues = (db.session.query(CVEGroup,
                                   CVE).join(CVEGroupEntry).join(CVE).group_by(
                                       CVEGroup.id).group_by(CVE.id))
        if group_ids:
            issues = issues.filter(CVEGroup.id.in_(group_ids))
        issues = (issues).all()

        if severity_changed:
            group_severity = defaultdict(list)
            for group, issue in issues:
                group_severity[group].append(issue.severity)
            for group, severities in group_severity.items():
                group.severity = highest_severity(severities)

        # update scheduled advisories if the issue type changes
        if advisories and issue_type_changed:
            group_issue_type = defaultdict(set)
            for group, issue in issues:
                group_issue_type[group].add(issue.issue_type)
            for advisory in advisories:
                if Publication.published == advisory.publication:
                    continue
                issue_types = group_issue_type[advisory.group_package.group]
                issue_type = 'multiple issues' if len(
                    issue_types) > 1 else next(iter(issue_types))
                advisory.advisory_type = issue_type

    db.session.commit()
    flash('Edited {}'.format(cve.id))
    return redirect('/{}'.format(cve.id))
def edit_group(avg):
    group_id = avg.replace('AVG-', '')
    group_data = (db.session.query(
        CVEGroup, CVE, func.group_concat(CVEGroupPackage.pkgname, ' '),
        Advisory).filter(CVEGroup.id == group_id).join(CVEGroupEntry).join(
            CVE).join(CVEGroupPackage).outerjoin(
                Advisory,
                Advisory.group_package_id == CVEGroupPackage.id).group_by(
                    CVEGroup.id).group_by(CVE.id).order_by(CVE.id)).all()
    if not group_data:
        return not_found()

    group = group_data[0][0]
    issues = [cve for (group, cve, pkg, advisory) in group_data]
    issue_ids = [cve.id for cve in issues]
    pkgnames = set(
        chain.from_iterable(
            [pkg.split(' ') for (group, cve, pkg, advisory) in group_data]))
    advisories = set(advisory for (group, cve, pkg, advisory) in group_data
                     if advisory)

    if not user_can_edit_group(advisories):
        return forbidden()

    form = GroupForm(pkgnames)
    if not form.is_submitted():
        form.affected.data = group.affected
        form.fixed.data = group.fixed
        form.pkgnames.data = "\n".join(sorted(pkgnames))
        form.status.data = status_to_affected(group.status).name
        form.reference.data = group.reference
        form.notes.data = group.notes
        form.bug_ticket.data = group.bug_ticket
        form.advisory_qualified.data = group.advisory_qualified and group.status is not Status.not_affected

        form.cve.data = "\n".join(issue_ids)
    if not form.validate_on_submit():
        if advisories:
            flash(
                'WARNING: This is referenced by an already published advisory!',
                'warning')
        return render_template('form/group.html',
                               title='Edit {}'.format(avg),
                               form=form,
                               CVEGroup=CVEGroup)

    pkgnames_edited = multiline_to_list(form.pkgnames.data)
    group.affected = form.affected.data
    group.fixed = form.fixed.data
    group.status = affected_to_status(Affected.fromstring(form.status.data),
                                      pkgnames_edited[0], group.fixed)
    group.bug_ticket = form.bug_ticket.data
    group.reference = form.reference.data
    group.notes = form.notes.data
    group.advisory_qualified = form.advisory_qualified.data and group.status is not Status.not_affected

    cve_ids = multiline_to_list(form.cve.data)
    cve_ids = set(filter(lambda s: s.startswith('CVE-'), cve_ids))
    issues_removed = set(filter(lambda issue: issue not in cve_ids, issue_ids))
    issues_added = set(filter(lambda issue: issue not in issue_ids, cve_ids))
    issues_final = set(
        filter(lambda issue: issue.id not in issues_removed, issues))

    if issues_removed:
        (db.session.query(CVEGroupEntry).filter(
            CVEGroupEntry.group_id == group.id).filter(
                CVEGroupEntry.cve_id.in_(issues_removed)).delete(
                    synchronize_session=False))
        for removed in issues_removed:
            flash('Removed {}'.format(removed))

    severities = [
        issue.severity for issue in list(
            filter(lambda issue: issue.id not in issues_removed, issues))
    ]
    for cve_id in issues_added:
        cve = db.get_or_create(CVE, id=cve_id)
        db.get_or_create(CVEGroupEntry, group=group, cve=cve)
        severities.append(cve.severity)
        issues_final.add(cve)
        flash('Added {}'.format(cve.id))
    group.severity = highest_severity(severities)

    pkgnames_removed = set(
        filter(lambda pkgname: pkgname not in pkgnames_edited, pkgnames))
    pkgnames_added = set(
        filter(lambda pkgname: pkgname not in pkgnames, pkgnames_edited))

    if pkgnames_removed:
        (db.session.query(CVEGroupPackage).filter(
            CVEGroupPackage.group_id == group.id).filter(
                CVEGroupPackage.pkgname.in_(pkgnames_removed)).delete(
                    synchronize_session=False))
        for removed in pkgnames_removed:
            flash('Removed {}'.format(removed))

    for pkgname in pkgnames_added:
        db.get_or_create(CVEGroupPackage, pkgname=pkgname, group=group)
        flash('Added {}'.format(pkgname))

    # update scheduled advisories
    for advisory in advisories:
        if Publication.published == advisory.publication:
            continue
        issue_type = 'multiple issues' if len(
            set([issue.issue_type for issue in issues_final])) > 1 else next(
                iter(issues_final)).issue_type
        advisory.advisory_type = issue_type

    db.session.commit()
    flash('Edited {}'.format(group.name))
    return redirect('/{}'.format(group.name))
def delete_issue(issue):
    entries = (db.session.query(CVE, CVEGroup, CVEGroupPackage, Advisory)
               .filter(CVE.id == issue)
               .outerjoin(CVEGroupEntry).outerjoin(CVEGroup).outerjoin(CVEGroupPackage)
               .outerjoin(Advisory, Advisory.group_package_id == CVEGroupPackage.id)
               .order_by(CVEGroup.created.desc()).order_by(CVEGroupPackage.pkgname)).all()
    if not entries:
        return not_found()

    issue = entries[0][0]
    advisories = set()
    groups = set()
    group_packages = defaultdict(set)
    for cve, group, pkg, advisory in entries:
        if group:
            groups.add(group)
            group_packages[group].add(pkg.pkgname)
        if advisory:
            advisories.add(advisory)

    if not user_can_delete_issue(advisories):
        return forbidden()

    group_ids = [group.id for group in groups]

    group_entries = (db.session.query(CVEGroup, CVE)
                     .join(CVEGroupEntry).join(CVE)
                     .order_by(CVE.id.desc()))
    if group_ids:
        group_entries = group_entries.filter(CVEGroup.id.in_(group_ids))
    group_entries = group_entries.all()

    group_issues = defaultdict(set)
    for group, cve in group_entries:
        group_issues[group].add(cve)

    groups = sorted(groups, key=lambda item: item.created, reverse=True)
    groups = sorted(groups, key=lambda item: item.status)
    group_packages = dict(map(lambda item: (item[0], sorted(item[1])), group_packages.items()))

    form = ConfirmForm()
    title = 'Delete {}'.format(issue)
    if not form.validate_on_submit():
        return render_template('form/delete_cve.html',
                               title=title,
                               heading=title,
                               form=form,
                               issue=issue,
                               groups=groups,
                               group_packages=group_packages,
                               group_issues=group_issues)

    if not form.confirm.data:
        return redirect('/{}'.format(issue))

    # delete groups that only contain this issue
    for group, issues in group_issues.items():
        if 0 == len(list(filter(lambda e: e.id != issue.id, issues))):
            flash('Deleted {}'.format(group))
            db.session.delete(group)

    db.session.delete(issue)
    db.session.commit()
    flash('Deleted {}'.format(issue))
    return redirect('/')
Beispiel #8
0
 def decorated_view(*args, **kwargs):
     if not current_user.role.is_administrator:
         return forbidden()
     return func(*args, **kwargs)
Beispiel #9
0
 def decorated_view(*args, **kwargs):
     if not current_user.role.is_security_team:
         return forbidden()
     return func(*args, **kwargs)
Beispiel #10
0
 def decorated_view(*args, **kwargs):
     if not current_user.role.is_reporter:
         return forbidden()
     return func(*args, **kwargs)