From 3c1dbbdc73e306ab9c9b15aa597a8be2f52bb98f Mon Sep 17 00:00:00 2001 From: Alejandro Gallardo Escobar <alex@artica.es> Date: Thu, 11 Dec 2014 16:10:15 +0100 Subject: [PATCH] File with double auth utilities to be accessed by ajax --- .../include/ajax/double_auth.ajax.php | 522 ++++++++++++++++++ 1 file changed, 522 insertions(+) create mode 100644 pandora_console/include/ajax/double_auth.ajax.php diff --git a/pandora_console/include/ajax/double_auth.ajax.php b/pandora_console/include/ajax/double_auth.ajax.php new file mode 100644 index 0000000000..770749e683 --- /dev/null +++ b/pandora_console/include/ajax/double_auth.ajax.php @@ -0,0 +1,522 @@ +<?php +// Pandora FMS - http://pandorafms.com +// ================================================== +// Copyright (c) 2005-2010 Artica Soluciones Tecnologicas +// Please see http://pandorafms.org for full contribution list + +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation for version 2. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +global $config; + +// Login check +check_login (); + +// Security check +$id_user = (string) get_parameter('id_user'); +if ($id_user !== $config['id_user']) { + db_pandora_audit("ACL Violation", + "Trying to access Double Authentication"); + echo json_encode(-1); + return; +} + +// Load the class +require_once ($config['homedir'].'/include/auth/GAuth/Auth.php'); + +// Default lenght of the secret +$secret_lenght = 16; +// Default lenght of the code +$code_lenght = 6; + +// Generate a new secret for the user +$generate_double_auth_secret = (bool) get_parameter('generate_double_auth_secret'); +if ($generate_double_auth_secret) { + $gAuth = new \GAuth\Auth(); + $code = $gAuth->generateCode($secret_lenght); + + echo json_encode($code); + return; +} + +// Validate the provided secret with a code provided by the user. +// If the parameter 'save' is set to true, the secret will +// be stored into the database. +// The results can be true, false or 1 if the validation is true +// but the secret can't be stored into the database. +$validate_double_auth_code = (bool) get_parameter('validate_double_auth_code'); +if ($validate_double_auth_code) { + $result = false; + + $secret = (string) get_parameter('secret'); + + if (!empty($secret) && strlen($secret) === $secret_lenght) { + $code = (string) get_parameter('code'); + + if (!empty($code) && strlen($code) === $code_lenght) { + $save = (bool) get_parameter('save'); + + if (!empty($code)) { + $gAuth = new \GAuth\Auth($secret); + $result = $gAuth->validateCode($code); + } + + if ($result && $save) { + // Delete the actual value (if exists) + $where = array( + 'id_user' => $id_user + ); + db_process_sql_delete('tuser_double_auth', $where); + + // Insert the new value + $values = array( + 'id_user' => $id_user, + 'secret' => $secret + ); + $result = (bool) db_process_sql_insert('tuser_double_auth', $values); + + if (!$result) { + $result = 1; + } + } + } + } + + echo json_encode($result); + return; +} + +// Set the provided secret to the user +$save_double_auth_secret = (bool) get_parameter('save_double_auth_secret'); +if ($save_double_auth_secret) { + $result = false; + + $secret = (string) get_parameter('secret'); + + if (strlen($secret) === $secret_lenght) { + // Delete the actual value (if exists) + $where = array( + 'id_user' => $id_user + ); + db_process_sql_delete('tuser_double_auth', $where); + // Insert the new value + $values = array( + 'id_user' => $id_user, + 'secret' => $secret + ); + $result = (bool) db_process_sql_insert('tuser_double_auth', $values); + } + + echo json_encode($result); + return; +} + +// Disable the double auth for the user +$deactivate_double_auth = (bool) get_parameter('deactivate_double_auth'); +if ($deactivate_double_auth) { + $result = false; + + // Delete the actual value (if exists) + $where = array( + 'id_user' => $id_user + ); + $result = db_process_sql_delete('tuser_double_auth', $where); + + echo json_encode($result); + return; +} + +// Get the info page to the container dialog +$get_double_auth_data_page = (bool) get_parameter('get_double_auth_data_page'); +if ($get_double_auth_data_page) { + $secret = db_get_value('secret', 'tuser_double_auth', 'id_user', $id_user); + + if (empty($secret)) { + return; + } + + $html = ''; + $html .= "<div class=\"left_align\">"; + $html .= "<p>"; + $html .= __('This is the private code that you should use with your authenticator app') . ". "; + $html .= __('You could enter the code manually or use the QR code to add it automatically') . "."; + $html .= "</p>"; + $html .= "</div>"; + $html .= "<div class=\"center_align\">"; + $html .= __('Code') . ": <b>$secret</b>"; + $html .= "<br>"; + $html .= __('QR') . ": <br>"; + $html .= "<div id=\"qr-container\"></div>"; + $html .= "</div>"; + + ob_clean(); +?> +<script type="text/javascript"> + var secret = "<?php echo $secret; ?>"; + var userID = "<?php echo $config['id_user']; ?>"; + + // QR code with the secret to add it to the app + paint_qrcode("otpauth://totp/"+userID+"?secret="+secret, $("div#qr-container").get(0), 200, 200); + + $("div#qr-container").attr("title", "").find("canvas").remove(); + // Don't delete this timeout. It's necessary to perform the style change. + // Chrome min. milliseconds: 1. + // Firefox min. milliseconds: 9. + setTimeout(function() { + $("div#qr-container").find("img").attr("style", ""); + }, 10); +</script> +<?php + $html .= ob_get_clean(); + + echo $html; + return; +} + +// Get the info page to the container dialog +$get_double_auth_info_page = (bool) get_parameter('get_double_auth_info_page'); +if ($get_double_auth_info_page) { + $container_id = (string) get_parameter('containerID'); + + $html = ''; + $html .= "<div class=\"left_align\">"; + $html .= "<p>"; + $html .= __('You are about to activate the double authentication') . ". "; + $html .= __('With this option enabled, your account access will be more secure, + cause a code generated by other application will be required after the login') . ". "; + $html .= "</p>"; + $html .= "<p>"; + $html .= __('You will need to install the app from the following link before continue') . ". "; + $html .= "</p>"; + $html .= "</div>"; + $html .= "<br>"; + $html .= "<div class=\"center_align\">"; + $html .= html_print_button(__('Download the app'), 'google_authenticator_download', false, '', '', true); + $html .= "</div>"; + $html .= "<br>"; + $html .= "<div class=\"center_align\">"; + $html .= html_print_button(__('Continue'), 'continue_to_generate', false, '', '', true); + $html .= "</div>"; + + ob_clean(); +?> +<script type="text/javascript"> + // Open the download page on click + $("input[name=\"google_authenticator_download\"]").click(function (e) { + e.preventDefault(); + window.open("https://support.google.com/accounts/answer/1066447"); + }); + + // Change the container content with the generation page + $("input[name=\"continue_to_generate\"]").click(function (e) { + e.preventDefault(); + + if (!confirm("<?php echo __('Are you installed the app yet?'); ?>")) { + return false; + } + + var containerID = "<?php echo $container_id; ?>"; + + $("#"+containerID).html("<img src=\"<?php echo $config['homeurl']; ?>/images/spinner.gif\" />"); + + $.ajax({ + url: 'ajax.php', + type: 'POST', + dataType: 'html', + data: { + page: 'include/ajax/double_auth.ajax', + id_user: "<?php echo $config['id_user']; ?>", + get_double_auth_generation_page: 1, + containerID: containerID + }, + complete: function(xhr, textStatus) { + + }, + success: function(data, textStatus, xhr) { + // isNaN = is not a number + if (isNaN(data)) { + $("#"+containerID).html(data); + } + // data is a number, convert it to integer to do the compare + else if (Number(data) === -1) { + $("#"+containerID).html("<?php echo '<b><div class=\"red\">' . __('Authentication error') . '</div></b>'; ?>"); + } + else { + $("#"+containerID).html("<?php echo '<b><div class=\"red\">' . __('Error') . '</div></b>'; ?>"); + } + }, + error: function(xhr, textStatus, errorThrown) { + $("#"+containerID).html("<?php echo '<b><div class=\"red\">' . __('There was an error loading the data') . '</div></b>'; ?>"); + } + }); + }); +</script> +<?php + $html .= ob_get_clean(); + + echo $html; + return; +} + +// Get the page that generates a secret for the user +$get_double_auth_generation_page = (bool) get_parameter('get_double_auth_generation_page'); +if ($get_double_auth_generation_page) { + $container_id = (string) get_parameter('containerID'); + + $gAuth = new \GAuth\Auth(); + $secret = $gAuth->generateCode($secret_lenght); + + $html = ''; + $html .= "<div class=\"center_align\">"; + $html .= "<p>"; + $html .= "<b>" . __('A private code has been generated') . "</b>."; + $html .= "</p>"; + $html .= "</div>"; + $html .= "<div class=\"left_align\">"; + $html .= "<p>"; + $html .= __('Before continue, you should create a new entry into the authenticator app') . ". "; + $html .= __('You could enter the code manually or use the QR code to add it automatically') . "."; + $html .= "</p>"; + $html .= "</div>"; + $html .= "<div class=\"center_align\">"; + $html .= __('Code') . ": <b>$secret</b>"; + $html .= "<br>"; + $html .= __('QR') . ": <br>"; + $html .= "<div id=\"qr-container\"></div>"; + $html .= "<br>"; + $html .= html_print_button(__('Refresh code'), 'continue_to_generate', false, '', '', true); + $html .= " "; + $html .= html_print_button(__('Continue'), 'continue_to_validate', false, '', '', true); + $html .= "</div>"; + + ob_clean(); +?> +<script type="text/javascript"> + var secret = "<?php echo $secret; ?>"; + var userID = "<?php echo $config['id_user']; ?>"; + + // QR code with the secret to add it to the app + paint_qrcode("otpauth://totp/"+userID+"?secret="+secret, $("div#qr-container").get(0), 200, 200); + + $("div#qr-container").attr("title", "").find("canvas").remove(); + // Don't delete this timeout. It's necessary to perform the style change. + // Chrome min. milliseconds: 1. + // Firefox min. milliseconds: 9. + setTimeout(function() { + $("div#qr-container").find("img").attr("style", ""); + }, 10); + + // Load the same page with another secret + $("input[name=\"continue_to_generate\"]").click(function(e) { + e.preventDefault(); + + var containerID = "<?php echo $container_id; ?>"; + + $("#"+containerID).html("<img src=\"<?php echo $config['homeurl']; ?>/images/spinner.gif\" />"); + + $.ajax({ + url: 'ajax.php', + type: 'POST', + dataType: 'html', + data: { + page: 'include/ajax/double_auth.ajax', + id_user: userID, + get_double_auth_generation_page: 1, + containerID: containerID + }, + complete: function(xhr, textStatus) { + + }, + success: function(data, textStatus, xhr) { + // isNaN = is not a number + if (isNaN(data)) { + $("#"+containerID).html(data); + } + // data is a number, convert it to integer to do the compare + else if (Number(data) === -1) { + $("#"+containerID).html("<?php echo '<b><div class=\"red\">' . __('Authentication error') . '</div></b>'; ?>"); + } + else { + $("#"+containerID).html("<?php echo '<b><div class=\"red\">' . __('Error') . '</div></b>'; ?>"); + } + }, + error: function(xhr, textStatus, errorThrown) { + $("#"+containerID).html("<?php echo '<b><div class=\"red\">' . __('There was an error loading the data') . '</div></b>'; ?>"); + } + }); + }); + + // Load the validation page + $("input[name=\"continue_to_validate\"]").click(function(e) { + e.preventDefault(); + + if (!confirm("<?php echo __('Are you introduced the code in the authenticator app yet?'); ?>")) { + return false; + } + + var containerID = "<?php echo $container_id; ?>"; + + $("#"+containerID).html("<img src=\"<?php echo $config['homeurl']; ?>/images/spinner.gif\" />"); + + $.ajax({ + url: 'ajax.php', + type: 'POST', + dataType: 'html', + data: { + page: 'include/ajax/double_auth.ajax', + id_user: "<?php echo $config['id_user']; ?>", + get_double_auth_validation_page: 1, + secret: secret, + containerID: containerID + }, + complete: function(xhr, textStatus) { + + }, + success: function(data, textStatus, xhr) { + // isNaN = is not a number + if (isNaN(data)) { + $("#"+containerID).html(data); + } + // data is a number, convert it to integer to do the compare + else if (Number(data) === -1) { + $("#"+containerID).html("<?php echo '<b><div class=\"red\">' . __('Authentication error') . '</div></b>'; ?>"); + } + else { + $("#"+containerID).html("<?php echo '<b><div class=\"red\">' . __('Error') . '</div></b>'; ?>"); + } + }, + error: function(xhr, textStatus, errorThrown) { + $("#"+containerID).html("<?php echo '<b><div class=\"red\">' . __('There was an error loading the data') . '</div></b>'; ?>"); + } + }); + }); +</script> +<?php + $html .= ob_get_clean(); + + echo $html; + return; +} + +// Get the validation page +$get_double_auth_validation_page = (bool) get_parameter('get_double_auth_validation_page'); +if ($get_double_auth_validation_page) { + $container_id = (string) get_parameter('containerID'); + $secret = (string) get_parameter('secret'); + + if (empty($secret) || strlen($secret) != $secret_lenght) { + echo json_encode(false); + return; + } + + $html = ''; + $html .= "<div class=\"left_align\">"; + $html .= "<p>"; + $html .= __('Introduce a code generated by the app') . ". "; + $html .= __('If the code is valid, the double authentication will be activated') . "."; + $html .= "</p>"; + $html .= "</div>"; + $html .= "<br>"; + $html .= "<div class=\"center_align\">"; + $html .= html_print_input_text('code', '', '', 50, $secret_lenght, true); + $html .= "<div id=\"code_input_message\" class=\"red\"></div>"; + $html .= "<br><br>"; + $html .= "<div id=\"button-container\">"; + $html .= html_print_button(__('Validate code'), 'continue_to_validate', false, '', '', true); + $html .= html_print_image ("images/spinner.gif", true); + $html .= "</div>"; + $html .= "</div>"; + + ob_clean(); +?> +<script type="text/javascript"> + $("div#button-container").find("img").hide(); + + // Start the error message hiden + $("div#code_input_message").hide(); + + var secret = "<?php echo $secret; ?>"; + + $("input#text-code").keypress(function() { + $(this).removeClass("red").css('border-color', '#cbcbcb'); + }); + + $("input[name=\"continue_to_validate\"]").click(function(e) { + e.preventDefault(); + + // Hide the error message + $("div#code_input_message").hide(); + + var containerID = "<?php echo $container_id; ?>"; + + $("input[name=\"continue_to_validate\"]").prop('enabled', false).hide(); + $("div#button-container").find("img").show(); + + $.ajax({ + url: 'ajax.php', + type: 'POST', + dataType: 'json', + data: { + page: 'include/ajax/double_auth.ajax', + id_user: "<?php echo $config['id_user']; ?>", + validate_double_auth_code: 1, + save: 1, + secret: secret, + code: function () { + return $("input#text-code").val(); + }, + containerID: containerID + }, + complete: function(xhr, textStatus) { + + }, + success: function(data, textStatus, xhr) { + // Valid code + if (data === true) { + $("#"+containerID).html("<b><?php echo '<b><div class=\"green\">' . __('The code is valid, you can exit now') . '</div></b>'; ?></b>"); + } + // Invalid code + else if (data === false) { + $("input[name=\"continue_to_validate\"]").prop('enabled', true).show(); + $("div#button-container").find("img").hide(); + $("input#text-code").addClass("red").css('border-color', '#c00'); + + $("div#code_input_message").html("<?php echo __('Invalid code'); ?>").show(); + } + // Valid code but not saved + else if (data === 1) { + $("input[name=\"continue_to_validate\"]").prop('enabled', true).show(); + $("div#button-container").find("img").hide(); + $("input#text-code").addClass("red").css('border-color', '#c00'); + + $("div#code_input_message").html("<?php echo __('The code is valid, but it was an error saving the data'); ?>").show(); + } + // Authentication error + else if (data === -1) { + $("#"+containerID).html("<?php echo '<b><div class=\"red\">' . __('Authentication error') . '</div></b>'; ?>"); + } + // Not expected results + else { + $("#"+containerID).html("<?php echo '<b><div class=\"red\">' . __('Error') . '</div></b>'; ?>"); + } + }, + error: function(xhr, textStatus, errorThrown) { + $("#"+containerID).html("<?php echo '<b><div class=\"red\">' . __('There was an error loading the data') . '</div></b>'; ?>"); + } + }); + }); +</script> +<?php + $html .= ob_get_clean(); + + echo $html; + return; +} + +return; +?> \ No newline at end of file