Explorar o código

Auth fix 0.9.8-20

Serghey Rodin %!s(int64=7) %!d(string=hai) anos
pai
achega
eaf9d89096
Modificáronse 6 ficheiros con 382 adicións e 63 borrados
  1. 40 0
      bin/v-check-api-key
  2. 100 0
      bin/v-check-user-hash
  3. 118 0
      bin/v-get-user-salt
  4. 9 0
      func/main.sh
  5. 46 14
      web/api/index.php
  6. 69 49
      web/login/index.php

+ 40 - 0
bin/v-check-api-key

@@ -0,0 +1,40 @@
+#!/bin/bash
+# info: check api key
+# options: KEY
+#
+# The function checks a key file in /usr/local/vesta/data/keys/
+
+
+#----------------------------------------------------------#
+#                    Variable&Function                     #
+#----------------------------------------------------------#
+
+if [ -z "$1" ]; then
+    echo "Error: key missmatch"
+    exit 9
+fi
+key=$(basename $1)
+ip=${2-127.0.0.1}
+time_n_date=$(date +'%T %F')
+time=$(echo "$time_n_date" |cut -f 1 -d \ )
+date=$(echo "$time_n_date" |cut -f 2 -d \ )
+
+
+#----------------------------------------------------------#
+#                       Action                             #
+#----------------------------------------------------------#
+
+if [ ! -e $VESTA/data/keys/$key ]; then
+    echo "Error: key missmatch"
+    echo "$date $time api $ip failed to login" >> $VESTA/log/auth.log
+    exit 9
+fi
+
+
+#----------------------------------------------------------#
+#                       Vesta                              #
+#----------------------------------------------------------#
+
+echo "$date $time api $ip successfully launched" >> $VESTA/log/auth.log
+
+exit

+ 100 - 0
bin/v-check-user-hash

@@ -0,0 +1,100 @@
+#!/bin/bash
+# info: check user hash
+# options: USER HASH [IP]
+#
+# The function verifies user hash
+
+
+#----------------------------------------------------------#
+#                    Variable&Function                     #
+#----------------------------------------------------------#
+
+# Argument definition
+user=$1
+hash=$2; HIDE=2
+ip=${3-127.0.0.1}
+
+# Includes
+source $VESTA/func/main.sh
+source $VESTA/conf/vesta.conf
+
+time_n_date=$(date +'%T %F')
+time=$(echo "$time_n_date" |cut -f 1 -d \ )
+date=$(echo "$time_n_date" |cut -f 2 -d \ )
+
+
+#----------------------------------------------------------#
+#                    Verifications                         #
+#----------------------------------------------------------#
+
+
+check_args '2' "$#" 'USER HASH'
+is_format_valid 'user'
+
+# Checking user
+if [ ! -d "$VESTA/data/users/$user" ] && [ "$user" != 'root' ]; then
+    echo "Error: password missmatch"
+    echo "$date $time $user $ip failed to login" >> $VESTA/log/auth.log
+    exit 9
+fi
+
+# Checking user hash
+is_hash_valid
+
+# Checking empty hash
+if [[ -z "$hash" ]]; then
+    echo "Error: password missmatch"
+    echo "$date $time $user $ip failed to login" >> $VESTA/log/auth.log
+    exit 9
+fi
+
+
+#----------------------------------------------------------#
+#                       Action                             #
+#----------------------------------------------------------#
+
+
+# Parsing user's salt
+shadow=$(grep "^$user:" /etc/shadow | cut -f 2 -d :)
+
+if echo "$shadow" | grep -qE '^\$[0-9a-z]+\$[^\$]+\$'
+then
+    salt=$(echo "$shadow" |cut -f 3 -d \$)
+    method=$(echo "$shadow" |cut -f 2 -d \$)
+    if [ "$method" -eq '1' ]; then
+        method='md5'
+    elif [ "$method" -eq '6' ]; then
+        method='sha-512'
+    else
+        echo "Error: password missmatch"
+        echo "$date $time $user $ip failed to login" >> $VESTA/log/auth.log
+        exit 9
+    fi
+else
+    salt=${shadow:0:2}
+    method='des'
+fi
+
+if [ -z "$salt" ]; then
+    echo "Error: password missmatch"
+    echo "$date $time $user $ip failed to login" >> $VESTA/log/auth.log
+    exit 9
+fi
+
+# Checking hash
+result=$(grep "^$user:$hash:" /etc/shadow 2>/dev/null)
+if [[ -z "$result" ]]; then
+    echo "Error: password missmatch"
+    echo "$date $time $user $ip failed to login" >> $VESTA/log/auth.log
+    exit 9
+fi
+
+
+#----------------------------------------------------------#
+#                       Vesta                              #
+#----------------------------------------------------------#
+
+# Logging
+echo "$date $time $user $ip successfully logged in" >> $VESTA/log/auth.log
+
+exit

+ 118 - 0
bin/v-get-user-salt

@@ -0,0 +1,118 @@
+#!/bin/bash
+# info: get user salt
+# options: USER [IP] [FORMAT]
+#
+# The function provides users salt
+
+
+#----------------------------------------------------------#
+#                    Variable&Function                     #
+#----------------------------------------------------------#
+
+# Argument definition
+user=$1
+ip=${2-127.0.0.1}
+format=${3-shell}
+
+# Includes
+source $VESTA/func/main.sh
+source $VESTA/conf/vesta.conf
+
+time_n_date=$(date +'%T %F')
+time=$(echo "$time_n_date" |cut -f 1 -d \ )
+date=$(echo "$time_n_date" |cut -f 2 -d \ )
+
+# JSON list function
+json_list() {
+    echo '{'
+    echo '    "'$user'": {
+        "METHOD": "'$method'",
+        "SALT": "'$salt'",
+        "TIME": "'$time'",
+        "DATE": "'$date'"
+        }'
+    echo '}'
+}
+
+# SHELL list function
+shell_list() {
+    echo "METHOD:         $method"
+    echo "SALT:           $salt"
+}
+
+# PLAIN list function
+plain_list() {
+    echo -e "$method\t$salt"
+}
+
+# CSV list function
+csv_list() {
+    echo "METHOD,SALT"
+    echo "$method, $salt"
+}
+
+
+#----------------------------------------------------------#
+#                    Verifications                         #
+#----------------------------------------------------------#
+
+
+check_args '1' "$#" 'USER [IP] [SALT]'
+is_format_valid 'user'
+
+# Checking user
+if [ ! -d "$VESTA/data/users/$user" ] && [ "$user" != 'root' ]; then
+    echo "Error: password missmatch"
+    echo "$date $time $user $ip failed to login" >> $VESTA/log/auth.log
+    exit 9
+fi
+
+
+#----------------------------------------------------------#
+#                       Action                             #
+#----------------------------------------------------------#
+
+# Parsing user's salt
+shadow=$(grep "^$user:" /etc/shadow | cut -f 2 -d :)
+
+if echo "$shadow" | grep -qE '^\$[0-9a-z]+\$[^\$]+\$'
+then
+    salt=$(echo "$shadow" |cut -f 3 -d \$)
+    method=$(echo "$shadow" |cut -f 2 -d \$)
+    if [ "$method" -eq '1' ]; then
+        method='md5'
+    elif [ "$method" -eq '6' ]; then
+        method='sha-512'
+    else
+        echo "Error: password missmatch"
+        echo "$date $time $user $ip failed to login" >> $VESTA/log/auth.log
+        exit 9
+    fi
+else
+    salt=${shadow:0:2}
+    method='des'
+fi
+
+if [ -z "$salt" ]; then
+    echo "Error: password missmatch"
+    echo "$date $time $user $ip failed to login" >> $VESTA/log/auth.log
+    exit 9
+fi
+
+
+# Listing data
+case $format in
+    json)   json_list ;;
+    plain)  plain_list ;;
+    csv)    csv_list ;;
+    shell)  shell_list ;;
+esac
+
+
+#----------------------------------------------------------#
+#                       Vesta                              #
+#----------------------------------------------------------#
+
+# Logging
+
+exit

+ 9 - 0
func/main.sh

@@ -278,6 +278,15 @@ is_password_valid() {
     fi
 }
 
+# Check if hash is transmitted via file
+is_hash_valid() {
+    if [[ "$hash" =~ ^/tmp/ ]]; then
+        if [ -f "$hash" ]; then
+            hash="$(head -n1 $hash)"
+        fi
+    fi
+}
+
 # Get object value
 get_object_value() {
     object=$(grep "$2='$3'" $USER_DATA/$1.conf)

+ 46 - 14
web/api/index.php

@@ -4,32 +4,64 @@ define('VESTA_CMD', '/usr/bin/sudo /usr/local/vesta/bin/');
 if (isset($_POST['user']) || isset($_POST['hash'])) {
 
     // Authentication
-    $auth_code = 1;
     if (empty($_POST['hash'])) {
-        // Check user permission to use API
         if ($_POST['user'] != 'admin') {
-            echo 'Error: only admin is allowed to use API';
+            echo 'Error: authentication failed';
             exit;
         }
 
-        $v_user = escapeshellarg($_POST['user']);
-        $v_password = tempnam("/tmp","vst");
-        $fp = fopen($v_password, "w");
-        fwrite($fp, $_POST['password']."\n");
+        $password = $_POST['password'];
+        $v_ip = escapeshellarg($_SERVER['REMOTE_ADDR']);
+        $output = '';
+        exec (VESTA_CMD."v-get-user-salt admin ".$v_ip." json" , $output, $return_var);
+        $pam = json_decode(implode('', $output), true);
+        $salt = $pam['admin']['SALT'];
+        $method = $pam['admin']['METHOD'];
+
+        if ($method == 'md5' ) {
+            $hash = crypt($password, '$1$'.$salt.'$');
+        }
+        if ($method == 'sha-512' ) {
+            $hash = crypt($password, '$6$rounds=5000$'.$salt.'$');
+            $hash = str_replace('$rounds=5000','',$hash);
+        }
+        if ($method == 'des' ) {
+            $hash = crypt($password, $salt);
+        }
+
+        // Send hash via tmp file
+        $v_hash = exec('mktemp -p /tmp');
+        $fp = fopen($v_hash, "w");
+        fwrite($fp, $hash."\n");
         fclose($fp);
-        $v_ip_addr = escapeshellarg($_SERVER["REMOTE_ADDR"]);
-        exec(VESTA_CMD ."v-check-user-password ".$v_user." ".escapeshellarg($v_password)." '".$v_ip_addr."'",  $output, $auth_code);
-        unlink($v_password);
-    /* No hash auth for security reason
+
+        // Check user hash
+        exec(VESTA_CMD ."v-check-user-hash admin ".$v_hash." ".$v_ip,  $output, $return_var);
+        unset($output);
+
+        // Remove tmp file
+        unlink($v_hash);
+
+        // Check API answer
+        if ( $return_var > 0 ) {
+            echo 'Error: authentication failed';
+            exit;
+        }
     } else {
         $key = '/usr/local/vesta/data/keys/' . basename($_POST['hash']);
         if (file_exists($key) && is_file($key)) {
-            $auth_code = '0';
+            exec(VESTA_CMD ."v-check-api-key ".escapeshellarg($key)." ".$v_ip,  $output, $return_var);
+            unset($output);
+
+            // Check API answer
+            if ( $return_var > 0 ) {
+                echo 'Error: authentication failed';
+                exit;
+            }
         }
-    */
     }
 
-    if ($auth_code != 0 ) {
+    if ( $return_var > 0 ) {
         echo 'Error: authentication failed';
         exit;
     }

+ 69 - 49
web/login/index.php

@@ -14,9 +14,6 @@ if (isset($_GET['logout'])) {
     session_destroy();
 }
 
-
-
-
 // Login as someone else
 if (isset($_SESSION['user'])) {
     if ($_SESSION['user'] == 'admin' && !empty($_GET['loginas'])) {
@@ -36,62 +33,85 @@ if (isset($_SESSION['user'])) {
 if (isset($_POST['user']) && isset($_POST['password'])) {
     if(isset($_SESSION['token']) && isset($_POST['token']) && $_POST['token'] == $_SESSION['token']) {
         $v_user = escapeshellarg($_POST['user']);
+        $v_ip = escapeshellarg($_SERVER['REMOTE_ADDR']);
 
-        // Send password via tmp file
-        $v_password = exec('mktemp -p /tmp');
-        $fp = fopen($v_password, "w");
-        fwrite($fp, $_POST['password']."\n");
-        fclose($fp);
-
-        // Check user & password
-        exec(VESTA_CMD ."v-check-user-password ".$v_user." ".escapeshellarg($v_password)." ".escapeshellarg($_SERVER['REMOTE_ADDR']),  $output, $return_var);
-        unset($output);
-
-        // Remove tmp file
-        unlink($v_password);
-
-        // Check API answer
+        // Get user's salt
+        $output = '';
+        exec (VESTA_CMD."v-get-user-salt ".$v_user." ".$v_ip." json" , $output, $return_var);
+        $pam = json_decode(implode('', $output), true);
         if ( $return_var > 0 ) {
             $ERROR = "<a class=\"error\">".__('Invalid username or password')."</a>";
-
         } else {
+            $user = $_POST['user'];
+            $password = $_POST['password'];
+            $salt = $pam[$user]['SALT'];
+            $method = $pam[$user]['METHOD'];
 
-            // Make root admin user
-            if ($_POST['user'] == 'root') $v_user = 'admin';
+            if ($method == 'md5' ) {
+                $hash = crypt($password, '$1$'.$salt.'$');
+            }
+            if ($method == 'sha-512' ) {
+                $hash = crypt($password, '$6$rounds=5000$'.$salt.'$');
+                $hash = str_replace('$rounds=5000','',$hash);
+            }
+            if ($method == 'des' ) {
+                $hash = crypt($password, $salt);
+            }
 
-            // Get user speciefic parameters
-            exec (VESTA_CMD . "v-list-user ".$v_user." json", $output, $return_var);
-            $data = json_decode(implode('', $output), true);
+            // Send hash via tmp file
+            $v_hash = exec('mktemp -p /tmp');
+            $fp = fopen($v_hash, "w");
+            fwrite($fp, $hash."\n");
+            fclose($fp);
 
-            // Define session user
-            $_SESSION['user'] = key($data);
-            $v_user = $_SESSION['user'];
+            // Check user hash
+            exec(VESTA_CMD ."v-check-user-hash ".$v_user." ".$v_hash." ".$v_ip,  $output, $return_var);
+            unset($output);
 
-            // Get user favorites
-            get_favourites();
+            // Remove tmp file
+            unlink($v_hash);
 
-            // Define language
-            $output = '';
-            exec (VESTA_CMD."v-list-sys-languages json", $output, $return_var);
-            $languages = json_decode(implode('', $output), true);
-            if(in_array($data[$v_user]['LANGUAGE'], $languages)){
-                $_SESSION['language'] = $data[$v_user]['LANGUAGE'];
-            }
-            else {
-                $_SESSION['language'] = 'en';
-            }
-        
-            // Regenerate session id to prevent session fixation
-            session_regenerate_id();
-
-            // Redirect request to control panel interface
-            if (!empty($_SESSION['request_uri'])) {
-                header("Location: ".$_SESSION['request_uri']);
-                unset($_SESSION['request_uri']);
-                exit;
+            // Check API answer
+            if ( $return_var > 0 ) {
+                $ERROR = "<a class=\"error\">".__('Invalid username or password')."</a>";
             } else {
-                header("Location: /");
-                exit;
+
+                // Make root admin user
+                if ($_POST['user'] == 'root') $v_user = 'admin';
+
+                // Get user speciefic parameters
+                exec (VESTA_CMD . "v-list-user ".$v_user." json", $output, $return_var);
+                $data = json_decode(implode('', $output), true);
+
+                // Define session user
+                $_SESSION['user'] = key($data);
+                $v_user = $_SESSION['user'];
+
+                // Get user favorites
+                get_favourites();
+
+                // Define language
+                $output = '';
+                exec (VESTA_CMD."v-list-sys-languages json", $output, $return_var);
+                $languages = json_decode(implode('', $output), true);
+                if (in_array($data[$v_user]['LANGUAGE'], $languages)){
+                    $_SESSION['language'] = $data[$v_user]['LANGUAGE'];
+                } else {
+                    $_SESSION['language'] = 'en';
+                }
+
+                // Regenerate session id to prevent session fixation
+                session_regenerate_id();
+
+                // Redirect request to control panel interface
+                if (!empty($_SESSION['request_uri'])) {
+                    header("Location: ".$_SESSION['request_uri']);
+                    unset($_SESSION['request_uri']);
+                    exit;
+                } else {
+                    header("Location: /");
+                    exit;
+                }
             }
         }
     } else {