--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
+ <head>
+ <title>ImmaeEu Account</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <link rel="stylesheet" href="https://assets.immae.eu/skeleton/2.0.4/skeleton.min.css" integrity="sha256-2YQRJMXD7pIAPHiXr0s+vlRWA7GYJEK0ARns7k2sbHY=" crossorigin="anonymous" />
+ <style type="text/css">
+ body {
+ font-family: Verdana,Arial,Courier New;
+ margin: auto;
+ }
+ table#ssh_keys_list textarea {
+ width: 100%;
+ height: 100%;
+ }
+ table#ssh_keys_list tbody tr.sshkeyrow {
+ height: 130px;
+ }
+ table#ssh_keys_list tbody tr.headrow th {
+ border-bottom: 0px !important;
+ padding-bottom: 0px !important;
+ }
+ table#ssh_keys_list tbody tr.mainrow td:not(.delete-button) {
+ border-bottom: 0px !important;
+ padding-bottom: 0px !important;
+ }
+ table#ssh_keys_list td.sshkey {
+ min-width: 600px;
+ height: 100%;
+ padding-top: 0px !important;
+ }
+
+ table#ssh_keys_list td.comment {
+ min-width: 160px;
+ }
+
+ </style>
+ </head>
+ <body>
+ <div class="container">
+ <h1>Gestion des clés SSH</h1>
+<?php
+
+$connection = NULL;
+
+session_start();
+
+// Liste des applications gérées
+const apps = [
+ 'git',
+ 'pub',
+ 'ftp',
+ 'ssh',
+ 'forward',
+];
+
+function checkSshKey($sshKey)
+{
+ $exploded = explode(' ', $sshKey);
+ if (count($exploded) != 2) {
+ return false;
+ }
+ if (!in_array($exploded[0], array('ssh-rsa', 'ssh-ed25519'))) {
+ return false;
+ }
+ $decoded = base64_decode($exploded[1], true);
+ if ($decoded === FALSE) {
+ return false;
+ }
+ $decoded = preg_replace("/[^\w\-]/","", (string) $decoded);
+ if (substr($decoded, 0, strlen($exploded[0])) !== $exploded[0]) {
+ return false;
+ }
+
+ return true;
+}
+
+function isUserLogged()
+{
+ return (isset($_SESSION["login"]) && doConnect() !== NULL);
+}
+
+function doConnect()
+{
+ global $connection;
+ $server = "ldaps://ldap.immae.eu";
+
+ if ($connection === NULL) {
+ $connection = ldap_connect($server);
+ ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, 3);
+ if (isset($_SESSION["user_dn"]) && isset($_SESSION["password"])) {
+ if (ldap_bind($connection, $_SESSION["user_dn"], $_SESSION["password"]) === false) {
+ $connection = NULL;
+ unset($_SESSION["user_dn"]);
+ unset($_SESSION["password"]);
+ unset($_SESSION["login"]);
+ }
+ }
+ }
+
+ return $connection;
+}
+
+function checkLogin($user, $password)
+{
+ $con = doConnect();
+
+ $user_dn = "uid=$user,ou=users,dc=immae,dc=eu";
+
+ if (ldap_bind($con, $user_dn, $password) === false) {
+ return false;
+ }
+ $_SESSION["user_dn"] = $user_dn;
+ $_SESSION["password"] = $password;
+
+ $user_search = ldap_search($con,"dc=immae,dc=eu","(uid=$user)");
+ $auth_entry = ldap_first_entry($con, $user_search);
+
+ return true;
+}
+
+function getLdapInfo()
+{
+ $con = doConnect();
+ if (!isset($_SESSION["user_dn"])) {
+ $sortieLdap = [];
+ } else {
+ $user_read = ldap_read($con, $_SESSION["user_dn"], "(objectclass=*)", array("uid","immaeSshKey"));
+ $user_entry = ldap_first_entry($con, $user_read);
+ $sortieLdap = ldap_get_values($con, $user_entry, "immaeSshKey");
+ unset($sortieLdap["count"]);
+ }
+
+ $keys = [];
+ foreach ($sortieLdap as $line) {
+ $exploded = explode(' ', $line);
+
+ $apps = explode('|', $exploded[0]);
+ $publicKey = $exploded[1] . ' ' . $exploded[2];
+
+ unset($exploded[0]);
+ unset($exploded[1]);
+ unset($exploded[2]);
+
+ $comment = implode(' ', $exploded);
+
+ $keys[] = [
+ 'apps' => $apps,
+ 'public_key' => $publicKey,
+ 'comment' => $comment,
+ ];
+ }
+
+ return $keys;
+}
+
+function pushLdapInfos($keys)
+{
+ $con = doConnect();
+ if (!isset($_SESSION["user_dn"]))
+ return false;
+
+ return ldap_mod_replace($con, $_SESSION["user_dn"], array("immaeSshKey" => $keys));
+}
+
+
+// Script
+if (isset($_POST['deconnexion'])) {
+ $_SESSION = [];
+}
+
+if (isset($_POST['sauvegarder'])) {
+ $editedKeys = [];
+ $errors = false;
+ $keysToSave = [];
+ foreach($_POST['keys'] as $id => $key) {
+ $editedKeys[$id] = $key;
+ if (!checkSshKey($key['public_key'])) {
+ $editedKeys[$id]['error'] = true;
+ $errors = true;
+ }
+
+ if (!isset($key['apps'])) {
+ $editedKeys[$id]['apps'] = $key['apps'] = [];
+
+ }
+ foreach ($key['apps'] as $app) {
+ if (!in_array($app, apps)) {
+ die("integrity");
+ }
+ }
+
+ if (!isset($editedKeys[$id]['error']) || $editedKeys[$id]['error'] !== true) {
+ $keysToSave[] = implode('|', $key['apps']) . ' ' . $key['public_key'] . ' ' . $key['comment'];
+ }
+ }
+
+ if (!$errors) {
+ $successSave = pushLdapInfos($keysToSave);
+ }
+}
+
+$loginErrors = "";
+if (isset($_POST['login'])) {
+ if (empty($_POST['username']) || empty($_POST['password'])) {
+ $loginErrors = "Le nom d'utilisateur et le mot de passe sont requis.";
+ } elseif (!checkLogin($_POST['username'], $_POST['password'])) {
+ $loginErrors = "Identifiants incorrects.";
+ } else {
+ $_SESSION['login'] = $_POST['username'];
+ }
+}
+
+if (isUserLogged()) :
+ $keys = isset($editedKeys) ? $editedKeys : getLdapInfo();
+?>
+ <p>Connecté en tant que <b><?= $_SESSION['login']; ?></b></p>
+
+ <form method="post">
+ <input type="submit" name="deconnexion" value="Déconnexion">
+ </form>
+
+ <?php if (isset($successSave) && $successSave === true) : ?>
+ <p style="color: green;">Clés enregistrées avec succès.</p>
+ <?php endif; ?>
+
+ <form method="post">
+ <table id="ssh_keys_list">
+ <tbody>
+ <?php
+ foreach ($keys as $id => $sshKey) :
+ ?>
+ <tr class="headrow">
+ <th>Description</th>
+ <?php foreach (apps as $app) : ?>
+ <th><?= $app ?></th>
+ <?php endforeach; ?>
+ <th></th>
+ </tr>
+ <tr class="mainrow">
+ <td class="comment"><textarea name="keys[<?= $id ?>][comment]"><?= $sshKey['comment'] ?></textarea></td>
+ <?php
+ foreach (apps as $app) :
+ $checked = in_array($app, $sshKey['apps']);
+ ?>
+ <td><input type="checkbox" name="keys[<?= $id ?>][apps][]" value="<?= $app ?>"<?= $checked ? ' checked' : '' ?>></td>
+ <?php endforeach; ?>
+ <td class="delete-button" rowspan="2"><button class="delete">Suppr.</button></td>
+ </tr>
+ <tr class="sshkeyrow">
+ <td colspan="<?php echo 1+count(apps); ?>" class="sshkey"><textarea name="keys[<?= $id ?>][public_key]" <?php if (isset($sshKey['error']) && $sshKey['error'] === true) :?>style="color: red"<?php endif; ?>><?= $sshKey['public_key'] ?></textarea></td>
+ </tr>
+ <?php
+ endforeach;
+ ?>
+ </tbody>
+ </table>
+
+ <button id="add">Ajouter</button>
+
+ <hr>
+
+ <input type="submit" value="Sauvegarder" name="sauvegarder">
+ </form>
+ <script>
+ function deleteLine(element) {
+ element.addEventListener('click', function(e) {
+ e.preventDefault();
+ e.target.closest('tr').remove();
+ }, false);
+ }
+
+ var suppr = document.getElementsByClassName('delete');
+ var add = document.getElementById('add');
+ var list = document.querySelector('#ssh_keys_list > tbody');
+
+ for (var i = 0; i < suppr.length; i++) {
+ deleteLine(suppr[i]);
+ }
+
+ add.addEventListener('click', function (e) {
+ e.preventDefault();
+ i++;
+
+ var newLine = `
+ <tr class="headrow">
+ <th>Description</th>
+ <?php foreach (apps as $app) : ?>
+ <th><?= $app ?></th>
+ <?php endforeach; ?>
+ <th></th>
+ </tr>
+ <tr class="mainrow">
+ <td class="comment"><textarea name="keys[${i}][comment]"></textarea></td>
+ `;
+
+
+ <?php
+ foreach (apps as $app) :
+ ?>
+ newLine += `<td><input type="checkbox" name="keys[${i}][apps][]" value="<?= $app ?>"></td>`;
+ <?php endforeach; ?>
+
+ newLine += `<td class="delete-button" rowspan="2"><button class="delete" id="delete-${i}">Suppr.</button></td>
+ </tr>`;
+
+ newLine += `<tr class="sshkeyrow">
+ <td colspan="<?php echo 1+count(apps); ?>" class="sshkey"><textarea name="keys[$[i}][public_key]"></textarea></td>
+ </tr>`;
+
+
+ list.insertAdjacentHTML('beforeend', newLine);
+
+ deleteLine(document.getElementById("delete-" + i));
+
+ }, false)
+ </script>
+<?php
+else:
+?>
+ <form action="" method="post">
+ <h2>Login</h2>
+
+ <?php
+ if (!empty($loginErrors)):
+ ?>
+ <p style="color: red;"><?= $loginErrors; ?></p>
+ <?php
+ endif;
+ ?>
+
+ <label for="username">Utilisateur :</label>
+ <input type="text" id="username" name="username"/>
+
+ <label for="password">Mot de passe :</label>
+ <input type="password" id="password" name="password"/>
+
+ <input type="submit" value="OK" name="login" />
+ </form>
+<?php
+endif;
+?>
+ </div>
+ </body>
+</html>
+
+