Projet

Général

Profil

Télécharger (2,98 ko) Statistiques
| Branche: | Tag: | Révision:

mandayejs / mandayejs / mandaye / models.py @ 83c9a56a

1
# mandayejs - saml reverse proxy
2
# Copyright (C) 2015  Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

    
17
import base64
18
from hashlib import sha256
19
from Crypto.Cipher import AES
20
from Crypto import Random
21

    
22
from django.db import models
23
from django.conf import settings
24
from django.utils.translation import ugettext_lazy as _
25
from django.utils.encoding import force_bytes
26

    
27
from jsonfield import JSONField
28

    
29
from mandayejs.mandaye.utils import get_password_field
30

    
31

    
32
class UserCredentials(models.Model):
33
    user = models.ForeignKey('auth.User')
34
    locators = JSONField(_('locators'), default={}, blank=True)
35
    linked = models.BooleanField(_('associated'), default=False, blank=True)
36

    
37
    class Meta:
38
        unique_together = ('user',)
39

    
40
    def __unicode__(self):
41
        return self.user.get_full_name() \
42
            or self.user.email \
43
            or self.user.username
44

    
45
    def save(self, *args, **kwargs):
46
        self.encrypt()
47
        super(UserCredentials, self).save(*args, **kwargs)
48

    
49
    def _get_cipher(self, iv):
50
        """Return cipher object
51
        """
52
        secret = sha256(force_bytes(settings.SECRET_KEY)).digest()
53
        return AES.new(secret, AES.MODE_CFB, iv)
54

    
55
    def encrypt(self,):
56
        """Encrypt password
57
        """
58
        password_field_name = get_password_field()
59
        iv = Random.get_random_bytes(16)
60
        cipher = self._get_cipher(iv)
61
        password = self.locators.get(password_field_name, '').encode('utf-8')
62
        crypted = cipher.encrypt(password)
63
        self.locators[password_field_name] = '%s$%s' % (base64.b64encode(iv),
64
                                                        base64.b64encode(crypted))
65
        return self.locators
66

    
67
    def decrypt(self,):
68
        """Decrypt password
69
        """
70
        password_field_name = get_password_field()
71
        try:
72
            iv, crypted = self.locators.get(password_field_name, '').split('$')
73
        except (ValueError, TypeError):
74
            return None
75
        try:
76
            iv = base64.b64decode(iv)
77
            crypted = base64.b64decode(crypted)
78
        except TypeError:
79
            return None
80
        cipher = self._get_cipher(iv)
81
        self.locators[password_field_name] = \
82
            cipher.decrypt(crypted).decode('utf-8')
83
        return self.locators
84

    
85
    def to_login_info(self, decrypt=False):
86
        if decrypt:
87
            self.decrypt()
88
        return {'#' + k: v for k, v in self.locators.items()}
(5-5/7)