Overview
Comment:Corrections de bugs sur l'activation de login OTP
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | dev
Files: files | file ages | folders
SHA1: 79ea6bcd4566e9a7363ecfcd02a179b0d6f317f1
User & Date: bohwaz on 2017-09-05 05:18:46
Other Links: branch diff | manifest | tags
Context
2017-09-05
05:59
Corrections pour la fonctionnalité "remember me" check-in: 864f2a278c user: bohwaz tags: dev
05:18
Corrections de bugs sur l'activation de login OTP check-in: 79ea6bcd45 user: bohwaz tags: dev
02:36
Modernisation / mise en objet des modifieurs et fonctions de template check-in: d2f4ecb4df user: bohwaz tags: dev
Changes

Modified src/include/lib/Garradin/Form.php from [0391534280] to [e13d9531e0].

91
92
93
94
95
96
97

98
99
100
101
102
103
104
		switch ($name)
		{
			case '_id': return 'identifiant';
			case 'passe': return 'mot de passe';
			case 'debut': return 'date de début';
			case 'fin': return 'date de fin';
			case 'duree': return 'durée';

			default: return $name;
		}
	}

	protected function getErrorMessage($rule, $element, Array $params)
	{
		$element = $this->getFieldName($element);







>







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
		switch ($name)
		{
			case '_id': return 'identifiant';
			case 'passe': return 'mot de passe';
			case 'debut': return 'date de début';
			case 'fin': return 'date de fin';
			case 'duree': return 'durée';
			case 'passe_check': return 'vérification de mot de passe';
			default: return $name;
		}
	}

	protected function getErrorMessage($rule, $element, Array $params)
	{
		$element = $this->getFieldName($element);

Modified src/include/lib/Garradin/Membres/Session.php from [ae5630354e] to [cc2ebcd25d].

120
121
122
123
124
125
126
127
128





129
130
131
132
133
134
135
136
137
138
139
				return false;
			}
		}

		return true;
	}

	public function generateNewOTPSecret()
	{





		$out = [];
		$out['secret'] = Security_OTP::getRandomSecret();
		$out['secret_display'] = implode(' ', str_split($out['secret'], 4));
		$out['url'] = Security_OTP::getOTPAuthURL(Config::getInstance()->get('nom_asso'), $out['secret']);
	
		$qrcode = new QRCode($out['url']);
		$out['qrcode'] = 'data:image/svg+xml;base64,' . base64_encode($qrcode->toSVG());

		return $out;
	}








|

>
>
>
>
>

|
|
|







120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
				return false;
			}
		}

		return true;
	}

	public function getOTPSecret($secret = null)
	{
		if (!$secret)
		{
			$secret = Security_OTP::getRandomSecret();
		}

		$out = [];
		$out['secret'] = $secret;
		$out['secret_display'] = implode(' ', str_split($secret, 4));
		$out['url'] = Security_OTP::getOTPAuthURL(Config::getInstance()->get('nom_asso'), $secret);
	
		$qrcode = new QRCode($out['url']);
		$out['qrcode'] = 'data:image/svg+xml;base64,' . base64_encode($qrcode->toSVG());

		return $out;
	}

220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
		$db->update('membres', ['passe' => $password], 'id = :id', ['id' => (int)$id]);

		return Utils::mail($membre->email, '['.$config->get('nom_asso').'] Nouveau mot de passe', $message);
	}

	public function editUser($data)
	{
		(new Membres)->edit($this->id, $data, false);
		$this->refresh();

		return true;
	}

	public function canAccess($category, $permission)
	{







|







225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
		$db->update('membres', ['passe' => $password], 'id = :id', ['id' => (int)$id]);

		return Utils::mail($membre->email, '['.$config->get('nom_asso').'] Nouveau mot de passe', $message);
	}

	public function editUser($data)
	{
		(new Membres)->edit($this->user->id, $data, false);
		$this->refresh();

		return true;
	}

	public function canAccess($category, $permission)
	{
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274

		return $out;
	}

	public function sendMessage($dest, $sujet, $message, $copie = false)
	{
		$from = $this->getUser();
		$from = $from['email'];
		// Uniquement adresse email pour le moment car faudrait trouver comment
		// indiquer le nom mais qu'il soit correctement échappé FIXME

		$config = Config::getInstance();

		$message .= "\n\n--\nCe message a été envoyé par un membre de ".$config->get('nom_asso');
		$message .= ", merci de contacter ".$config->get('email_asso')." en cas d'abus.";







|







265
266
267
268
269
270
271
272
273
274
275
276
277
278
279

		return $out;
	}

	public function sendMessage($dest, $sujet, $message, $copie = false)
	{
		$from = $this->getUser();
		$from = $from->email;
		// Uniquement adresse email pour le moment car faudrait trouver comment
		// indiquer le nom mais qu'il soit correctement échappé FIXME

		$config = Config::getInstance();

		$message .= "\n\n--\nCe message a été envoyé par un membre de ".$config->get('nom_asso');
		$message .= ", merci de contacter ".$config->get('email_asso')." en cas d'abus.";
314
315
316
317
318
319
320
321
322
323
324
325
326
			if (!$this->getPGPFingerprint($data['clef_pgp']))
			{
				throw new UserException('Clé PGP invalide : impossible d\'extraire l\'empreinte.');
			}
		}

		$db = DB::getInstance();
		$db->update('membres', $data, $db->where('id', (int)$this->id));
		$this->refresh();

		return true;
	}
}







|





319
320
321
322
323
324
325
326
327
328
329
330
331
			if (!$this->getPGPFingerprint($data['clef_pgp']))
			{
				throw new UserException('Clé PGP invalide : impossible d\'extraire l\'empreinte.');
			}
		}

		$db = DB::getInstance();
		$db->update('membres', $data, $db->where('id', (int)$this->user->id));
		$this->refresh();

		return true;
	}
}

Modified src/templates/admin/mes_infos_securite.tpl from [3052ddb707] to [7c9c1d22c9].

1
2
3
4
5
6






7
8
9
10
11
12
13




14
15
16
17
18
19
20
{include file="admin/_head.tpl" title="Mes informations de connexion et sécurité" current="mes_infos" js=1}

<ul class="actions">
    <li><a href="{$admin_url}mes_infos.php">Mes informations personnelles</a></li>
    <li class="current"><a href="{$admin_url}mes_infos_securite.php">Mot de passe et options de sécurité</a></li>
</ul>







{form_errors}

{if $confirm}
    <form method="post" action="{$self_url}">

    {if !empty($otp)}




        <p class="alert">
            Confirmez l'activation de l'authentification à double facteur TOTP en l'utilisant une première fois.
        </p>

        <fieldset>
            <legend>Confirmer l'activation de l'authentification à double facteur (2FA)</legend>
            <img class="qrcode" src="{$otp.qrcode}" alt="" />






>
>
>
>
>
>




|

|
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{include file="admin/_head.tpl" title="Mes informations de connexion et sécurité" current="mes_infos" js=1}

<ul class="actions">
    <li><a href="{$admin_url}mes_infos.php">Mes informations personnelles</a></li>
    <li class="current"><a href="{$admin_url}mes_infos_securite.php">Mot de passe et options de sécurité</a></li>
</ul>

{if $ok}
<p class="confirm">
    Changements enregistrés.
</p>
{/if}

{form_errors}

{if $confirm}
    <form method="post" action="{$self_url_no_qs}">

    {if !empty($otp) && $otp == 'disable'}
        <p class="alert">
            Confirmez la désactivation de l'authentification à double facteur TOTP.
        </p>
    {elseif !empty($otp)}
        <p class="alert">
            Confirmez l'activation de l'authentification à double facteur TOTP en l'utilisant une première fois.
        </p>

        <fieldset>
            <legend>Confirmer l'activation de l'authentification à double facteur (2FA)</legend>
            <img class="qrcode" src="{$otp.qrcode}" alt="" />
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

47

48
49
50
51
52
53
54
55
56
57
58
59
60
61
    {/if}

    <fieldset>
        <legend>Confirmer les changements</legend>
        <dl>
            <dt><label for="f_passe_confirm">Mot de passe actuel</label></dt>
            <dd class="help">Entrez votre mot de passe actuel pour confirmer les changements demandés.</dd>
            <dd><input type="password" name="passe_confirm" /></dd>
        </dl>
    </fieldset>

    <p class="submit">
        {csrf_field key="edit_me_security"}
        <input type="hidden" name="passe" value="{form_field name="passe"}" />
        <input type="hidden" name="passe_confirmed" value="{form_field name="passe_confirmed"}" />
        <input type="hidden" name="clef_pgp" value="{form_field name="clef_pgp"}" />

        <input type="hidden" name="otp_secret" value="{$otp.secret}" />

        <input type="submit" name="confirm" value="Confirmer &rarr;" />
    </p>

    </form>
{else}

    <form method="post" action="{$self_url}">

        <fieldset>
            <legend>Changer mon mot de passe</legend>
            {if $user.droit_membres < Garradin\Membres::DROIT_ADMIN && (!empty($champs.passe.private) || empty($champs.passe.editable))}
                <p class="help">Vous devez contacter un administrateur pour changer votre mot de passe.</p>
            {else}
                <dl>







|








>

>






|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
    {/if}

    <fieldset>
        <legend>Confirmer les changements</legend>
        <dl>
            <dt><label for="f_passe_confirm">Mot de passe actuel</label></dt>
            <dd class="help">Entrez votre mot de passe actuel pour confirmer les changements demandés.</dd>
            <dd><input type="password" name="passe_check" /></dd>
        </dl>
    </fieldset>

    <p class="submit">
        {csrf_field key="edit_me_security"}
        <input type="hidden" name="passe" value="{form_field name="passe"}" />
        <input type="hidden" name="passe_confirmed" value="{form_field name="passe_confirmed"}" />
        <input type="hidden" name="clef_pgp" value="{form_field name="clef_pgp"}" />
        {if !empty($otp)}
        <input type="hidden" name="otp_secret" value="{$otp.secret}" />
        {/if}
        <input type="submit" name="confirm" value="Confirmer &rarr;" />
    </p>

    </form>
{else}

    <form method="post" action="{$self_url_no_qs}">

        <fieldset>
            <legend>Changer mon mot de passe</legend>
            {if $user.droit_membres < Garradin\Membres::DROIT_ADMIN && (!empty($champs.passe.private) || empty($champs.passe.editable))}
                <p class="help">Vous devez contacter un administrateur pour changer votre mot de passe.</p>
            {else}
                <dl>

Modified src/www/admin/mes_infos_securite.php from [c21c21da4f] to [28a0163964].

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37




38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?php

namespace Garradin;

require_once __DIR__ . '/_inc.php';

$confirm = false;

if (f('confirm'))
{
    $form->check('edit_me_security', [
        'passe'       => 'confirmed|min:6',
        'passe_check' => 'required',

    ]);

    if (f('passe_check') && !$session->checkPassword(f('passe_check')))
    {
        $form->addError('Le mot de passe fourni ne correspond pas au mot de passe actuel. Merci de bien vouloir renseigner votre mot de passe courant pour confirmer les changements.');
    }
    elseif (f('otp_secret') && !$session->checkOTP(f('otp_secret'), f('code')))
    {
        $form->addError('Le code TOTP entré n\'est pas valide.');
    }

    if (!$form->hasErrors())
    {
        try {
            $data = [
                'clef_pgp' => f('clef_pgp'),
            ];

            if (f('passe') && !empty($config->get('champs_membres')->get('passe')->editable))
            {
                $data['passe'] = f('passe');
            }

            if (f('otp_secret'))




            {
                $data['secret_otp'] = f('otp_secret');
            }
            elseif (f('otp') == 'disable')
            {
                $data['secret_otp'] = null;
            }

            $session->editSecurity($data);
            Utils::redirect('/admin/');
        }
        catch (UserException $e)
        {
            $form->addError($e->getMessage());
        }
    }














>


|



|
















|
>
>
>
>



<
|
<
<
<

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

46



47
48
49
50
51
52
53
54
55
<?php

namespace Garradin;

require_once __DIR__ . '/_inc.php';

$confirm = false;

if (f('confirm'))
{
    $form->check('edit_me_security', [
        'passe'       => 'confirmed|min:6',
        'passe_check' => 'required',
        'code' => 'required_with:otp_secret',
    ]);

    if (f('passe_check') && !$session->checkPassword(f('passe_check'), $user->passe))
    {
        $form->addError('Le mot de passe fourni ne correspond pas au mot de passe actuel. Merci de bien vouloir renseigner votre mot de passe courant pour confirmer les changements.');
    }
    elseif (f('code') && !$session->checkOTP(f('otp_secret'), f('code')))
    {
        $form->addError('Le code TOTP entré n\'est pas valide.');
    }

    if (!$form->hasErrors())
    {
        try {
            $data = [
                'clef_pgp' => f('clef_pgp'),
            ];

            if (f('passe') && !empty($config->get('champs_membres')->get('passe')->editable))
            {
                $data['passe'] = f('passe');
            }

            if (f('otp_secret') == 'disable')
            {
                $data['secret_otp'] = null;
            }
            elseif (f('otp_secret') !== null)
            {
                $data['secret_otp'] = f('otp_secret');
            }





            $session->editSecurity($data);
            Utils::redirect('/admin/mes_infos_securite.php?ok');
        }
        catch (UserException $e)
        {
            $form->addError($e->getMessage());
        }
    }

71
72
73
74
75
76
77
78



79
80
81
82
83
84
85
86
87
88
89
90
    }
}

$tpl->assign('confirm', $confirm);

if (f('otp') == 'generate')
{
    $otp = $session->getNewOTPSecret();



    $tpl->assign('otp', $otp);
}
elseif (f('otp_secret'))
{
    $tpl->assign('otp', f('otp_secret'));
}
else
{
    $tpl->assign('otp', false);
}

$tpl->assign('pgp_disponible', \KD2\Security::canUseEncryption());







|
>
>
>
|



|







72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
    }
}

$tpl->assign('confirm', $confirm);

if (f('otp') == 'generate')
{
    $tpl->assign('otp', $session->getNewOTPSecret());
}
elseif (f('otp') == 'disable')
{
    $tpl->assign('otp', 'disable');
}
elseif (f('otp_secret'))
{
    $tpl->assign('otp', $session->getOTPSecret(f('otp_secret')));
}
else
{
    $tpl->assign('otp', false);
}

$tpl->assign('pgp_disponible', \KD2\Security::canUseEncryption());
98
99
100
101
102
103
104

105
106

$tpl->assign('clef_pgp_fingerprint', $fingerprint);

$tpl->assign('passphrase', Utils::suggestPassword());
$tpl->assign('champs', $config->get('champs_membres')->getAll());

$tpl->assign('membre', $user);


$tpl->display('admin/mes_infos_securite.tpl');







>


102
103
104
105
106
107
108
109
110
111

$tpl->assign('clef_pgp_fingerprint', $fingerprint);

$tpl->assign('passphrase', Utils::suggestPassword());
$tpl->assign('champs', $config->get('champs_membres')->getAll());

$tpl->assign('membre', $user);
$tpl->assign('ok', qg('ok') !== null);

$tpl->display('admin/mes_infos_securite.tpl');