#!/usr/bin/env python
# -*- coding: utf-8 -*-

__license__= """
GoLismero 2.0 - The web knife - Copyright (C) 2011-2014

Golismero project site: https://github.com/golismero
Golismero project mail: contact@golismero-project.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
"""

__all__ = ["WeakCredentials"]

from .. import Vulnerability
from ... import identity
from ...information import Information
from ...information.auth import Username, Password
from ...resource import Resource


#------------------------------------------------------------------------------
class WeakCredentials(Vulnerability):
    """
    Weak Credentials.

    Credentials to a secure resource were successfully guessed.
    This typically means the chosen password was either predictable
    or too weak.

    Enforce a secure password policy to prevent easily guessable passwords
    from being used.
    """

    DEFAULTS = Vulnerability.DEFAULTS.copy()
    DEFAULTS["level"]     = "high"
    DEFAULTS["cvss_base"] = "9.0"
    DEFAULTS["cwe"]       = "CWE-522"


    #--------------------------------------------------------------------------
    def __init__(self, target, username, password, **kwargs):
        """
        :param target: Vulnerable resource or information.
        :type target: Resource | Information

        :param username: User name.
        :type username: Username

        :param password: Password.
        :type password: Password
        """

        # Validate the parameters.
        if (
            not isinstance(target, Resource) and
            not isinstance(target, Information)
        ):
            raise TypeError("Expected Resource or Information, got %r instead"
                            % type(target))
        if not isinstance(username, Username):
            raise TypeError("Expected Username, got %r instead" % type(username))
        if not isinstance(password, Password):
            raise TypeError("Expected Password, got %r instead" % type(password))

        # Save the properties.
        self.__username_id = username.identity
        self.__password_id = password.identity
        self.__username = username.name
        self.__password = password.password

        # Parent constructor.
        super(WeakCredentials, self).__init__(target, **kwargs)

        # Link the vulnerability to the data.
        self.add_information(username)
        self.add_information(password)

        # Link the username and the password together.
        username.add_information(password)

    __init__.__doc__ += Vulnerability.__init__.__doc__[
            Vulnerability.__init__.__doc__.find("\n        :keyword"):]


    #--------------------------------------------------------------------------
    @identity
    def username_id(self):
        """
        :returns: Identity hash of the Username object.
        :rtype: str
        """
        return self.__username_id


    #--------------------------------------------------------------------------
    @property
    def username(self):
        """
        :returns: User name.
        :rtype: Username
        """
        return self.__username


    #--------------------------------------------------------------------------
    @identity
    def password_id(self):
        """
        :returns: Identity hash of the Password object.
        :rtype: str
        """
        return self.__password_id


    #--------------------------------------------------------------------------
    @property
    def password(self):
        """
        :returns: Password.
        :rtype: Password
        """
        return self.__password


    #--------------------------------------------------------------------------
    @property
    def display_properties(self):
        props = super(WeakCredentials, self).display_properties
        details = props["Details"]
        del details["Username ID"]
        del details["Password ID"]
        details["Username"] = self.username
        details["Password"] = self.password
        return props
