Ver Fonte

Merge branch 'manage-sshkeys' of clement/BIM into master

Clément Krebs há 2 anos atrás
pai
commit
48912f9597

+ 3 - 1
includes/config.ini.example

@@ -1,4 +1,6 @@
 [ldap_server]
 hostname = "example.com"
 port = "389"
-basedn = "ou=people,dc=example,dc=com"
+basedn = "ou=people,dc=example,dc=com"
+binddn = "cn=admin,dc=example,dc=com"
+bindpw = "SECRET"

+ 4 - 0
public/index.php

@@ -2,6 +2,7 @@
 require_once '../vendor/autoload.php';
 
 require_once __DIR__ . '/../src/controllers/user.php';
+require_once __DIR__ . '/../src/controllers/ssh.php';
 
 function get_view($view_name) {
     try {
@@ -23,6 +24,9 @@ $dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
     $r->addRoute('GET', '/changepassword', 'form_password');
     $r->addRoute('POST', '/changepassword', 'change_password');
     $r->addRoute('GET', '/signout', 'signout');
+    $r->addRoute('GET', '/ssh', 'form_ssh');
+    $r->addRoute('POST', '/addsshkey', 'add_ssh_key');
+    $r->addRoute('POST', '/delsshkey', 'del_ssh_key');
 });
 
 // Fetch method and URI from somewhere

+ 80 - 0
src/controllers/ssh.php

@@ -0,0 +1,80 @@
+<?php
+require_once '../src/models/ssh.php';
+
+function form_ssh() {
+    session_start();
+
+    if (!isset($_SESSION['user'])) {
+        header('Location: signin');
+        exit();
+    }
+
+    if (!$_SESSION['IS_SSH']) {
+        header ('Location: home');
+        exit();
+    }
+
+    $ssh_keys = SshModel\get_ssh_keys($_SESSION['user']);
+    $_SESSION["SSH_KEYS"] = $ssh_keys;
+
+    $template = get_view("sshhomepage");
+
+    echo $template->render();
+    unset($_SESSION['message']);
+}
+
+function add_ssh_key() {
+    session_start();
+
+    if (!isset($_SESSION['user'])) {
+        header('Location: /');
+        exit();
+    }
+
+    if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+        header('Location: /');
+        exit();
+    }
+
+    if (!isset($_POST['new_ssh_key'])) {
+        header('Location: ssh');
+        exit();
+    }
+
+    $res = SshModel\add_ssh_key($_SESSION['user'], $_POST['new_ssh_key']);
+
+    if (!$res) {
+        $_SESSION['message'] = "There was a problem adding the key, contact admins";
+    }
+
+    header('Location: ssh');
+    exit();
+}
+
+function del_ssh_key() {
+    session_start();
+
+    if (!isset($_SESSION['user'])) {
+        header('Location: /');
+        exit();
+    }
+
+    if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+        header('Location: /');
+        exit();
+    }
+
+    if (!isset($_POST['key_to_delete'])) {
+        header('Location: ssh');
+        exit();
+    }
+
+    $res = SshModel\del_ssh_key($_SESSION['user'], $_POST['key_to_delete']);
+
+    if (!$res) {
+        $_SESSION['message'] = "There was a problem deleting the key, contact admins";
+    }
+
+    header('Location: ssh');
+    exit();
+}

+ 5 - 2
src/controllers/user.php

@@ -108,13 +108,16 @@ function auth() {
 
     $id = htmlspecialchars($_POST['id']);
 
-    if (!UserModel\auth($id, $_POST['password'])) {
-        $_SESSION['message'] = "Wrong username or password";
+    $auth_res = UserModel\auth($id, $_POST['password']);
+
+    if (!$auth_res[0]) {
+        $_SESSION['message'] = $auth_res[1];
         header('Location: /');
         exit();
     }
 
     $_SESSION['user'] = $id;
+    $_SESSION['IS_SSH'] = $auth_res[1]['IS_SSH'];
     header('Location: home');
     exit();
 }

+ 93 - 0
src/models/ssh.php

@@ -0,0 +1,93 @@
+<?php
+
+namespace SshModel;
+
+function get_ssh_keys($id) {
+    $ini = parse_ini_file('../includes/config.ini');
+    try {
+        $ldapconn = ldap_connect($ini['hostname'], $ini['port']);
+        ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
+        ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
+    } catch (Exception $e) {
+        die ('ERROR: ' . $e->getMessage());
+    }
+
+    $filter = "(&(uid=" . $id . ")(objectClass=ldapPublicKey))";
+    $attributes = array("ldapPublicKey");
+
+    if ($ldapconn) {
+        $ldap_bind = ldap_bind($ldapconn, $ini['binddn'], $ini["bindpw"]);
+        if ($ldap_bind) {
+            $res = ldap_search($ldapconn, $ini['basedn'], $filter, $attributes);
+            $info = ldap_get_entries($ldapconn, $res);
+            if ($info["count"] > 0) {
+                $keys = array();
+                // if user has ssh keys
+                if (isset($info[0]["sshpublickey"])) {
+                    for ($i = 0; $i < $info[0]["sshpublickey"]["count"]; $i++) {
+                        $key = $info[0]["sshpublickey"][$i];
+                        $key_name = array();
+                        preg_match("/\S+@\S+/", $key, $key_name);
+                        $keys[] = [$key_name[0] => $key];
+                    }
+                    return $keys;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+function add_ssh_key($id, $new_key) {
+    $ini = parse_ini_file('../includes/config.ini');
+    try {
+        $ldapconn = ldap_connect($ini['hostname'], $ini['port']);
+        ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
+        ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
+    } catch (Exception $e) {
+        die ('ERROR: ' . $e->getMessage());
+    }
+
+    if (!$ldapconn) {
+        return false;
+    }
+
+    $ldap_bind = @ldap_bind($ldapconn, $ini['binddn'], $ini["bindpw"]);
+
+    if (!$ldap_bind) {
+        return false;
+    }
+
+    $dn = "uid=" . $id . "," . $ini['basedn'];
+    $entry['sshPublicKey'] = $new_key;
+    $res = @ldap_mod_add($ldapconn, $dn, $entry);
+
+    return $res;
+}
+
+function del_ssh_key($id, $key) {
+    $ini = parse_ini_file('../includes/config.ini');
+    try {
+        $ldapconn = ldap_connect($ini['hostname'], $ini['port']);
+        ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
+        ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
+    } catch (Exception $e) {
+        die ('ERROR: ' . $e->getMessage());
+    }
+
+    if (!$ldapconn) {
+        return false;
+    }
+
+    $ldap_bind = @ldap_bind($ldapconn, $ini['binddn'], $ini["bindpw"]);
+
+    if (!$ldap_bind) {
+        return false;
+    }
+
+    $dn = "uid=" . $id . "," . $ini['basedn'];
+    $entry["sshPublicKey"] = $key;
+    $res = @ldap_mod_del($ldapconn, $dn, $entry);
+
+    return $res;
+}

+ 45 - 4
src/models/user.php

@@ -2,6 +2,41 @@
 
 namespace UserModel;
 
+function get_user_infos($id) {
+    $ini = parse_ini_file('../includes/config.ini');
+    try {
+        $ldapconn = ldap_connect($ini['hostname'], $ini['port']);
+        ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
+        ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
+    } catch (Exception $e) {
+        die ('ERROR: ' . $e->getMessage());
+    }
+
+    if (!$ldapconn) {
+        return false;
+    }
+
+    $ldapbind = @ldap_bind($ldapconn, $ini["binddn"], $ini["bindpw"]);
+    if (!$ldapbind) {
+        return false;
+    }
+
+    // Check if user can store ssh keys
+    $filter = "(&(uid=" . $id . ")(objectClass=ldapPublicKey))";
+    $attributes = array("ldapPublicKey");
+    
+    $res = ldap_search($ldapconn, $ini["basedn"], $filter, $attributes);
+    $info = ldap_get_entries($ldapconn, $res);
+
+    if ($info["count"] > 0) {
+        $is_ssh = true;
+    } else {
+        $is_ssh = false;
+    }
+
+    return array("IS_SSH" => $is_ssh);
+}
+
 function auth($id, $passwd) {
     $ini = parse_ini_file('../includes/config.ini');
     try {
@@ -13,12 +48,18 @@ function auth($id, $passwd) {
     }
     
     if ($ldapconn) {
+
         $ldapbind = @ldap_bind($ldapconn, "uid=" . ldap_escape($id) . ',' . $ini["basedn"], $passwd);
-        if ($ldapbind) {
-            return true;
-        } else {
-            return false;
+
+        $user_infos = get_user_infos($id);
+        if (!$user_infos) {
+            return array(false, "A problem occured getting your account informations, contact admins");
         }
+        if (!$ldapbind) {
+            return array(false, "Wrong username or password");
+        }
+
+        return array(true, $user_infos);
     }   
 }
 

+ 3 - 0
templates/home.html.twig

@@ -8,6 +8,9 @@
         <ul>
             <li><a href="changepassword">Change password</a></li>
             <li><a href="signout">Sign out</a></li>
+            {% if session.IS_SSH %}
+            <li><a href="ssh">Manage SSH Keys</a></li>
+            {% endif %}
         </ul>
     </body>
 </html>

+ 46 - 0
templates/sshhomepage.html.twig

@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>BIM</title>
+        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
+    </head>
+    <style>
+        body {word-break: break-all;}
+    </style>
+    <body class="layout-default">
+        <div class="section">
+            {% for keys in session.SSH_KEYS %}
+                {% for key_name, key_value in keys %}
+                    <article class="message is-primary">
+                        <div class="message-header">
+                            <div>{{ key_name }}</div>
+                        </div>
+                        <div class="message-body">
+                            {{ key_value }} </br></br>
+                            <form method="post" accept-charset="UTF-8" action="delsshkey">
+                            <button type="submit" name="key_to_delete" value="{{ key_value }}" class="button is-danger">Delete</button>
+                            </form>
+                        </div>
+                    </article>
+                {% endfor %}
+            {% endfor %}
+        </div>
+        <div class="section">
+            <form method="post" accept-charset="UTF-8" action="addsshkey" class="box">
+                <div class="field">
+                    <label for="new_ssh_key" class="label">New SSH key</label>
+                    <div class="control">
+                        <input id="new_ssh_key" type="text" name="new_ssh_key" class="input is-rounded is-primary">
+                    </div>
+                </div>
+
+                <button class="button is-primary">Add</button>
+            </form>
+        </div>
+        {% if session.message is defined %}
+            <div class="container">
+                <div class="box notification is-warning">{{ session.message }}</div>
+            </div>
+        {% endif %}
+    </body>
+</html>