Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# -*- coding: utf-8 -*- # 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 version 3 for # more details. # # You should have received a copy of the GNU General Public License version 3 # along with this program; if not, write to the Free Software Foundation, Inc., 51 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # (c) 2015-2016 Valentin Samir
except ImportError: from django.core.urlresolvers import reverse
#: logger facility
"""Encode a python object to json"""
""" Function that add somes variable to the context before template rendering
:param dict params: The context dictionary used to render templates. :return: The ``params`` dictionary with the key ``settings`` set to :obj:`django.conf.settings`. :rtype: dict """
else:
# use info as default infox type # make box discardable by default six.text_type(msg["message"]).encode("utf-8") + msg["type"].encode("utf-8") ) # hash depend of the rendering language
""" Wrapper dumping `data` to a json and sending it to the user with an HttpResponse
:param django.http.HttpRequest request: The request object used to generate this response. :param dict data: The python dictionnary to return as a json :return: The content of ``data`` serialized in json :rtype: django.http.HttpResponse """
""" transform a python dotted path to the attr
:param path: A dotted path to a python object or a python object :type path: :obj:`unicode` or :obj:`str` or anything :return: The python object pointed by the dotted path or the python object unchanged """ # if we got a str, decode it to unicode (normally it should only contain ascii) # if path is not an unicode, return it unchanged (may be it is already the attribute to import)
""" Redirect to ``url_name`` with ``params`` as querystring
:param unicode url_name: a URL pattern name :param params: Some parameter to append to the reversed URL :type params: :obj:`dict` or :obj:`NoneType<types.NoneType>` :return: A redirection to the URL with name ``url_name`` with ``params`` as querystring. :rtype: django.http.HttpResponseRedirect """
""" compute the reverse url of ``url_name`` and add to it parameters from ``params`` as querystring
:param unicode url_name: a URL pattern name :param params: Some parameter to append to the reversed URL :type params: :obj:`dict` or :obj:`NoneType<types.NoneType>` :param **kwargs: additional parameters needed to compure the reverse URL :return: The computed reverse URL of ``url_name`` with possible querystring from ``params`` :rtype: unicode """ else:
""" copy a :class:`django.http.QueryDict` in a :obj:`dict` ignoring keys in the set ``ignore``
:param django.http.QueryDict get_or_post_params: A GET or POST :class:`QueryDict<django.http.QueryDict>` :param set ignore: An optinal set of keys to ignore during the copy :return: A copy of get_or_post_params :rtype: dict """
""" Set the cookie ``key`` on ``response`` with value ``value`` valid for ``max_age`` secondes
:param django.http.HttpResponse response: a django response where to set the cookie :param unicode key: the cookie key :param unicode value: the cookie value :param int max_age: the maximum validity age of the cookie """ datetime.utcnow() + timedelta(seconds=max_age), "%a, %d-%b-%Y %H:%M:%S GMT" ) key, value, max_age=max_age, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN, secure=settings.SESSION_COOKIE_SECURE or None )
""" Giving a django request, return the current http url, possibly ignoring some GET parameters
:param django.http.HttpRequest request: The current request object. :param set ignore_params: An optional set of GET parameters to ignore :return: The URL of the current page, possibly omitting some parameters from ``ignore_params`` in the querystring. :rtype: unicode """
""" update parameters using ``params`` in the ``url`` query string
:param url: An URL possibily with a querystring :type url: :obj:`unicode` or :obj:`str` :param dict params: A dictionary of parameters for updating the url querystring :return: The URL with an updated querystring :rtype: unicode """ # make the params order deterministic if not isinstance(url_query, bytes): # pragma: no cover in python3 urlencode return an unicode url_query = url_query.encode("utf-8")
""" If exception are stacked, return the first one
:param error: A python exception with possible exception embeded within :return: A python exception with no exception embeded within """ else: else:
""" Generate a ticket with prefix ``prefix`` and length ``lg``
:param unicode prefix: An optional prefix (probably ST, PT, PGT or PGTIOU) :param int lg: The length of the generated ticket (with the prefix) :return: A randomlly generated ticket of length ``lg`` :rtype: unicode """ random.choice( string.ascii_letters + string.digits ) for _ in range(lg - len(prefix or "") - 1) ) else:
""" Generate a Login Ticket
:return: A ticket with prefix ``settings.CAS_LOGIN_TICKET_PREFIX`` and length ``settings.CAS_LT_LEN`` :rtype: unicode """
""" Generate a Service Ticket
:return: A ticket with prefix ``settings.CAS_SERVICE_TICKET_PREFIX`` and length ``settings.CAS_ST_LEN`` :rtype: unicode """
""" Generate a Proxy Ticket
:return: A ticket with prefix ``settings.CAS_PROXY_TICKET_PREFIX`` and length ``settings.CAS_PT_LEN`` :rtype: unicode """
""" Generate a Proxy Granting Ticket
:return: A ticket with prefix ``settings.CAS_PROXY_GRANTING_TICKET_PREFIX`` and length ``settings.CAS_PGT_LEN`` :rtype: unicode """
""" Generate a Proxy Granting Ticket IOU
:return: A ticket with prefix ``settings.CAS_PROXY_GRANTING_TICKET_IOU_PREFIX`` and length ``settings.CAS_PGTIOU_LEN`` :rtype: unicode """
""" Generate an saml id
:return: A random id of length ``settings.CAS_TICKET_LEN`` :rtype: unicode """
""" :param tuple nuplet: A tuple :param int index: An index :param default: An optional default value :return: ``nuplet[index]`` if defined, else ``default`` (possibly ``None``) """
""" Validate a salt as crypt salt
:param str salt: a password salt :return: ``True`` if ``salt`` is a valid crypt salt on this system, ``False`` otherwise :rtype: bool """ else: else: else: else: else:
""" Class to deal with hashed password as defined at https://tools.ietf.org/id/draft-stroeder-hashed-userpassword-values-01.html """
#: valide schemes that require a salt #: valide sschemes that require no slat
#: map beetween scheme and hash function b"{SMD5}": hashlib.md5, b"{MD5}": hashlib.md5, b"{SSHA}": hashlib.sha1, b"{SHA}": hashlib.sha1, b"{SSHA256}": hashlib.sha256, b"{SHA256}": hashlib.sha256, b"{SSHA384}": hashlib.sha384, b"{SHA384}": hashlib.sha384, b"{SSHA512}": hashlib.sha512, b"{SHA512}": hashlib.sha512 }
#: map between scheme and hash length b"{SMD5}": 16, b"{SSHA}": 20, b"{SSHA256}": 32, b"{SSHA384}": 48, b"{SSHA512}": 64, }
""" Error raised then the hash scheme is not in :attr:`LdapHashUserPassword.schemes_salt` + :attr:`LdapHashUserPassword.schemes_nosalt` """
"""Error raised then the hash is too short"""
"""Error raised then, with the scheme ``{CRYPT}``, the salt is invalid"""
def _raise_bad_scheme(cls, scheme, valid, msg): """ Raise :attr:`BadScheme` error for ``scheme``, possible valid scheme are in ``valid``, the error message is ``msg``
:param bytes scheme: A bad scheme :param list valid: A list a valid scheme :param str msg: The error template message :raises LdapHashUserPassword.BadScheme: always """
def _test_scheme(cls, scheme): """ Test if a scheme is valide or raise BadScheme
:param bytes scheme: A scheme :raises BadScheme: if ``scheme`` is not a valid scheme """ scheme, cls.schemes_salt | cls.schemes_nosalt, "The scheme %r is not valid. Valide schemes are %s." )
def _test_scheme_salt(cls, scheme): """ Test if the scheme need a salt or raise BadScheme
:param bytes scheme: A scheme :raises BadScheme: if ``scheme` require no salt """ scheme, cls.schemes_salt, "The scheme %r is only valid without a salt. Valide schemes with salt are %s." )
def _test_scheme_nosalt(cls, scheme): """ Test if the scheme need no salt or raise BadScheme
:param bytes scheme: A scheme :raises BadScheme: if ``scheme` require a salt """ scheme, cls.schemes_nosalt, "The scheme %r is only valid with a salt. Valide schemes without salt are %s." )
""" Hash ``password`` with ``scheme`` using ``salt``. This three variable beeing encoded in ``charset``.
:param bytes scheme: A valid scheme :param bytes password: A byte string to hash using ``scheme`` :param bytes salt: An optional salt to use if ``scheme`` requires any :param str charset: The encoding of ``scheme``, ``password`` and ``salt`` :return: The hashed password encoded with ``charset`` :rtype: bytes """ else: cls._schemes_to_hash[scheme](password + salt).digest() + salt ) if six.PY3: password = password.decode(charset) salt = salt.decode(charset) if six.PY3: hashed_password = hashed_password.encode(charset)
def get_scheme(cls, hashed_passord): """ Return the scheme of ``hashed_passord`` or raise :attr:`BadHash`
:param bytes hashed_passord: A hashed password :return: The scheme used by the hashed password :rtype: bytes :raises BadHash: if no valid scheme is found within ``hashed_passord`` """
def get_salt(cls, hashed_passord): """ Return the salt of ``hashed_passord`` possibly empty
:param bytes hashed_passord: A hashed password :return: The salt used by the hashed password (empty if no salt is used) :rtype: bytes :raises BadHash: if no valid scheme is found within ``hashed_passord`` or if the hashed password is too short for the scheme found. """ else:
""" Check that ``password`` match `hashed_password` using ``method``, assuming the encoding is ``charset``.
:param str method: on of ``"crypt"``, ``"ldap"``, ``"hex_md5"``, ``"hex_sha1"``, ``"hex_sha224"``, ``"hex_sha256"``, ``"hex_sha384"``, ``"hex_sha512"``, ``"plain"`` :param password: The user inputed password :type password: :obj:`str` or :obj:`unicode` :param hashed_password: The hashed password as stored in the database :type hashed_password: :obj:`str` or :obj:`unicode` :param str charset: The used char encoding (also used internally, so it must be valid for the charset used by ``password`` when it was initially ) :return: True if ``password`` match ``hashed_password`` using ``method``, ``False`` otherwise :rtype: bool """ elif hashed_password.startswith(b'_'): # pragma: no cover old BSD format not supported salt = hashed_password[:9] else: if six.PY3: password = password.decode(charset) salt = salt.decode(charset) hashed_password = hashed_password.decode(charset) method.startswith("hex_") and method[4:] in {"md5", "sha1", "sha224", "sha256", "sha384", "sha512"} ): hashlib, method[4:] )(password).hexdigest().encode("ascii") == hashed_password.lower() else:
""" decode a version string following version semantic http://semver.org/ input a tuple of int. It will work as long as we do not use pre release versions.
:param unicode version: A dotted version :return: A tuple a int :rtype: tuple """
""" Fetch the last version from pypi and return it. On successful fetch from pypi, the response is cached 24h, on error, it is cached 10 min.
:return: the last django-cas-server version :rtype: unicode """ else: except ( KeyError, ValueError, requests.exceptions.RequestException ) as error: # pragma: no cover (should not happen unless pypi is not available) logger.error( "Unable to fetch %s: %s" % (settings.CAS_NEW_VERSION_JSON_URL, error) ) last_version._cache = (time.time(), version, False)
"Return all rows from a django cursor as a dict" dict(zip(columns, row)) for row in cursor.fetchall() ]
""" Forge a SLO logout request
:param unicode ticket: A ticket value :return: A SLO XML body request :rtype: unicode """ ID="%(id)s" Version="2.0" IssueInstant="%(datetime)s"> <saml:NameID xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"></saml:NameID> <samlp:SessionIndex>%(ticket)s</samlp:SessionIndex> </samlp:LogoutRequest>""" % { 'id': gen_saml_id(), 'datetime': timezone.now().isoformat(), 'ticket': ticket }
""" Test that ``value`` is a valid regular expression
:param unicode value: A regular expression to test :raises ValidationError: if ``value`` is not a valid regular expression """ _('"%(value)s" is not a valid regular expression'), params={'value': value} ) |