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: 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
...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
...
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
...
314
315
316
317
318
319
320
321
322
323
324
325
326
				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;
	}

................................................................................
		$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)
	{
................................................................................

		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.";
................................................................................
			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;
	}
}







|

>
>
>
>
>

|
|
|







 







|







 







|







 







|





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
...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
...
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
...
319
320
321
322
323
324
325
326
327
328
329
330
331
				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;
	}

................................................................................
		$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)
	{
................................................................................

		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.";
................................................................................
			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
..
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
{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="" />
................................................................................
    {/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>






>
>
>
>
>
>




|

>
>
>
>
|







 







|








>

>






|







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
..
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
{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="" />
................................................................................
    {/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].

7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
..
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
..
71
72
73
74
75
76
77
78



79
80
81
82
83
84
85
86
87
88
89
90
..
98
99
100
101
102
103
104

105
106
$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 {
................................................................................
            ];

            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());
        }
    }

................................................................................
    }
}

$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());
................................................................................

$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');







>


|



|







 







|
>
>
>
>



<
|
<
<
<

|







 







|
>
>
>
|



|







 







>


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
..
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
..
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
...
102
103
104
105
106
107
108
109
110
111
$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 {
................................................................................
            ];

            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());
        }
    }

................................................................................
    }
}

$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());
................................................................................

$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');