diff --git a/pandora_console/attachment/downloads/.gitignore b/pandora_console/attachment/downloads/.gitignore deleted file mode 100644 index 1a4baf536d..0000000000 --- a/pandora_console/attachment/downloads/.gitignore +++ /dev/null @@ -1 +0,0 @@ - diff --git a/pandora_console/extensions/api_checker.php b/pandora_console/extensions/api_checker.php index b4af7c77ee..895d621178 100755 --- a/pandora_console/extensions/api_checker.php +++ b/pandora_console/extensions/api_checker.php @@ -1,67 +1,144 @@ $url, 'result' => $result, ]; - - return $return; } +/** + * Perform API Checker + * + * @return void. + */ function extension_api_checker() { global $config; check_login(); - if (! check_acl($config['id_user'], 0, 'PM')) { + if ((bool) check_acl($config['id_user'], 0, 'PM') === false) { db_pandora_audit( AUDIT_LOG_ACL_VIOLATION, 'Trying to access Profile Management' @@ -85,11 +162,12 @@ function extension_api_checker() $return_type = io_safe_output(get_parameter('return_type', '')); $other = io_safe_output(get_parameter('other', '')); $other_mode = io_safe_output(get_parameter('other_mode', 'url_encode_separator_|')); + $token = get_parameter('token'); - $api_execute = get_parameter('api_execute', 0); + $api_execute = (bool) get_parameter('api_execute', false); $return_call_api = ''; - if ($api_execute) { + if ($api_execute === true) { $return_call_api = api_execute( $url, $ip, @@ -103,7 +181,8 @@ function extension_api_checker() urlencode($id2), $return_type, urlencode($other), - $other_mode + $other_mode, + $token ); } @@ -129,6 +208,11 @@ function extension_api_checker() $row[] = html_print_input_text('pandora_url', $pandora_url, '', 50, 255, true); $table->data[] = $row; + $row = []; + $row[] = __('API Token').ui_print_help_tip(__('Use API Token instead API Pass, User and Password.'), true); + $row[] = html_print_input_text('token', $token, '', 50, 255, true); + $table->data[] = $row; + $row = []; $row[] = __('API Pass'); $row[] = html_print_input_password('apipass', $apipass, '', 50, 255, true); @@ -214,7 +298,7 @@ function extension_api_checker() echo ''; echo ''; - if ($api_execute) { + if ($api_execute === true) { echo '
'; echo ''.__('Result').''; echo __('URL').'
'; diff --git a/pandora_console/extras/mr/60.sql b/pandora_console/extras/mr/60.sql index 7be8a0b4ef..9b2c360dbc 100644 --- a/pandora_console/extras/mr/60.sql +++ b/pandora_console/extras/mr/60.sql @@ -46,4 +46,6 @@ update `tmodule_inventory` set `code`='IyEvdXNyL2Jpbi9wZXJsCiMjIyMjIyMjIyMjIyMjI update `tmodule_inventory` set `code`='IyEvdXNyL2Jpbi9wZXJsCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgcGFuZG9yYV9wcm9kdWN0SUQucGwKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBDb3B5cmlnaHQgKGMpIDIwMTUgQm9yamEgU2FuY2hleiwgPGZib3JqYS5zYW5jaGV6QGFydGljYS5lcz4KIyAgICAgICAgICAgKGMpIDIwMTUgQXJ0aWNhIFNvbHVjaW9uZXMgVGVjbm9sb2dpY2FzIFMuTAojCiMgVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vcgojIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlCiMgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IHZlcnNpb24gMi4KIwojIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAojIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiMgTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQojIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiMgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKIyBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQojIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEsIFVTQS4KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiN1c2Ugc3RyaWN0Owp1c2Ugd2FybmluZ3M7Cgp1c2UgRmlsZTo6QmFzZW5hbWU7CnVzZSBIVE1MOjpFbnRpdGllcyAoKTsKCiMgQ2hlY2sgZm9yIHdtaWMKbXkgJHdtaV9jbGllbnQgPSAiL3Vzci9iaW4vcGFuZG9yYXdtaWMiOwp1bmxlc3MoLWUgJHdtaV9jbGllbnQpIHsKCXByaW50ICJbZXJyb3JdICR3bWlfY2xpZW50IG5vdCBmb3VuZC5cbiI7CglleGl0IDE7Cn0KCmlmICgkI0FSR1YgIT0gMikgewoJcHJpbnQgIlVzYWdlOiAkMCA8dGFyZ2V0IGlwPiA8dXNlcm5hbWU+IDxwYXNzd29yZD5cbiI7CglleGl0IDE7Cn0KCm15ICR0YXJnZXRfaXAgPSAkQVJHVlswXTsKbXkgJHVzZXJuYW1lID0gJEFSR1ZbMV07Cm15ICRwYXNzd29yZCA9ICRBUkdWWzJdOwoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBTVUIgcnVuX3F1ZXJ5ICgkd3FsX3F1ZXJ5KQojIFJ1bnMgdGhlIGdpdmVuIFdRTCBxdWVyeSBhbmQgcmV0dXJucyB0aGUgcmVzdWx0IGFzIGFuIGFycmF5IG9mIGhhc2hlcy4KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKc3ViIHJ1bl9xdWVyeSB7CglteSAkd3FsX3F1ZXJ5ID0gJF9bMF07CglteSBAcmVzdWx0ID0ge307CgoJJHdxbF9xdWVyeSA9fiAncy8iL1wnL2cnOwoKCSMgUnVuIHRoZSBEQ09NL1dNSSBjbGllbnQKCW15ICRvdXRwdXQgPSBgJHdtaV9jbGllbnQgLVUgJyR1c2VybmFtZSclJyRwYXNzd29yZCcgLy8kdGFyZ2V0X2lwIFwiJHdxbF9xdWVyeVwiIDI+L2Rldi9udWxsYDsKCglteSBAbGluZXMgPSBzcGxpdCgvXG4vLCAkb3V0cHV0KTsKCSMgSGVhZGVyLCBkZXNjcmlwdGlvbiwgcmVzdWx0cwoJaWYgKCQjbGluZXMgPCAyKSB7CgkJZXhpdCAxOwoJfQoJIyBEcm9wIHRoZSBoZWFkZXIKCXNoaWZ0IChAbGluZXMpOwoJCQoJIyBHZXQgY29sdW1uIG5hbWVzCglteSBAY29sdW1uX25hbWVzID0gc3BsaXQoL1x8Lywgc2hpZnQgKEBsaW5lcykpOwoKCSMgR2V0IHJvdyBkYXRhCglteSAkaWR4ID0gMDsKCWZvciAobXkgJGkgPSAwOyAkaSA8PSAkI2xpbmVzOyAkaSsrKSB7CgkJIyBDaGVjayBmb3IgZXJyb3JzCgkJaWYgKCRsaW5lc1skaV0gPX4gbS9eRVJST1IvKSB7CgkJCWV4aXQgMTsKCQl9CgoJCSMgQmxhY2sgbGlzdAoJCWlmICgkbGluZXNbJGldID1+IG0vRmlsZSAxLykgewoJCQluZXh0OwoJCX0KCQlteSBAY29sdW1uID0gc3BsaXQoL1x8LywgJGxpbmVzWyRpXSk7CgkJZm9yIChteSAkaiA9IDA7ICRqIDw9ICQjY29sdW1uX25hbWVzOyAkaisrKSB7CgkJCWlmICghIGRlZmluZWQoJGNvbHVtblskal0pKSB7CgkJCQkkcmVzdWx0WyRpZHhdLT57JGNvbHVtbl9uYW1lc1skal19ID0gIiI7CgkJCX0KCQkJZWxzZSB7CgkJCQkkcmVzdWx0WyRpZHhdLT57JGNvbHVtbl9uYW1lc1skal19ID0gJGNvbHVtblskal07CgkJCX0KCQl9CgkJCgkJJGlkeCsrOwoJfQoJCglyZXR1cm4gQHJlc3VsdDsKfQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBTVUIgcHJpbnRfbW9kdWxlZGF0YSAoJG1vZHVsZV9pdGVtLCAkbW9kdWxlX2RhdGEsIAojICRtb2R1bGVfZGVzY3JpcHRpb24sIEBkYXRhKQojIFByaW50cyBhIG1vZHVsZWRhdGEgWE1MIHRhZy4gJG1vZHVsZV9pdGVtLCAkbW9kdWxlX2RhdGEgYW5kCiMgJG1vZHVsZV9kZXNjcmlwdGlvbiBhcmUgdXNlZCB0byBpbmRleCB0aGUgaXRlbSwgZGF0YSBhbmQgZGVzY3JpcHRpb24KIyBYTUwgdGFncyByZXNwZWN0aXZlbHkuCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCnN1YiBwcmludF9tb2R1bGVkYXRhIHsKCW15IEBtb2R1bGVfaGVhZGVycyA9IEB7JF9bMF19OwoJbXkgQG1vZHVsZV91bml0cyAgID0gQHskX1sxXX07CglteSBAZGF0YSAgICAgICAgICAgPSBAeyRfWzJdfTsKCW15ICRyZXN1bHQ7Cglmb3JlYWNoIG15ICRlbGVtZW50IChAZGF0YSkgewoJCSRyZXN1bHQgPSAnJzsKCQlmb3IgKCRpPTA7ICRpPEBtb2R1bGVfaGVhZGVyczskaSsrKSB7CgkJCWlmIChkZWZpbmVkICgkZWxlbWVudC0+eyRtb2R1bGVfaGVhZGVyc1skaV19KSkgewoJCQkJJHJlc3VsdCAuPSAkZWxlbWVudC0+eyRtb2R1bGVfaGVhZGVyc1skaV19IC4gJG1vZHVsZV91bml0c1skaV0gLiAnOyc7CgkJCX0KCQkJZWxzZSB7CgkJCQkkcmVzdWx0IC49ICc7JzsKCQkJfQoJCX0KCQljaG9wKCRyZXN1bHQpOwoJCXByaW50ICRyZXN1bHQgLiAiXG4iOwkKCX0KfQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBNYWluCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgpteSBAcmVzdWx0ICA9IHJ1bl9xdWVyeSgiU2VsZWN0IFNlcmlhbE51bWJlciBmcm9tIFdpbjMyX09wZXJhdGluZ1N5c3RlbSIpOwojIFJlbWVtYmVyIHRvIG1hdGNoIGxlbmdodCBvZiBib3RoIGFycmF5cyBoZWFkZXJzICYgdW5pdHMKbXkgQGhlYWRlcnMgPSAoIlNlcmlhbE51bWJlciIpOwpteSBAdW5pdHMgICA9ICgiIik7CnByaW50X21vZHVsZWRhdGEgKFxAaGVhZGVycyxcQHVuaXRzLCBcQHJlc3VsdCk7CmV4aXQgMDsKCg==' where `code`='IyEvdXNyL2Jpbi9wZXJsCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgcGFuZG9yYV9wcm9kdWN0SUQucGwKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBDb3B5cmlnaHQgKGMpIDIwMTUgQm9yamEgU2FuY2hleiwgPGZib3JqYS5zYW5jaGV6QGFydGljYS5lcz4KIyAgICAgICAgICAgKGMpIDIwMTUgQXJ0aWNhIFNvbHVjaW9uZXMgVGVjbm9sb2dpY2FzIFMuTAojCiMgVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vcgojIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlCiMgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IHZlcnNpb24gMi4KIwojIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAojIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCiMgTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZQojIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCiMgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UKIyBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZQojIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEsIFVTQS4KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiN1c2Ugc3RyaWN0Owp1c2Ugd2FybmluZ3M7Cgp1c2UgRmlsZTo6QmFzZW5hbWU7CnVzZSBIVE1MOjpFbnRpdGllcyAoKTsKCiMgQ2hlY2sgZm9yIHdtaWMKbXkgJHdtaV9jbGllbnQgPSAid21pYyI7CmlmIChzeXN0ZW0oIiR3bWlfY2xpZW50ID4gL2Rldi9udWxsIDI+JjEiKSAhPSAyNTYpIHsKCXByaW50ICJbZXJyb3JdICR3bWlfY2xpZW50IG5vdCBmb3VuZC5cbiI7CglleGl0IDE7Cn0KCmlmICgkI0FSR1YgIT0gMikgewoJcHJpbnQgIlVzYWdlOiAkMCA8dGFyZ2V0IGlwPiA8dXNlcm5hbWU+IDxwYXNzd29yZD5cbiI7CglleGl0IDE7Cn0KCm15ICR0YXJnZXRfaXAgPSAkQVJHVlswXTsKbXkgJHVzZXJuYW1lID0gJEFSR1ZbMV07Cm15ICRwYXNzd29yZCA9ICRBUkdWWzJdOwoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBTVUIgcnVuX3F1ZXJ5ICgkd3FsX3F1ZXJ5KQojIFJ1bnMgdGhlIGdpdmVuIFdRTCBxdWVyeSBhbmQgcmV0dXJucyB0aGUgcmVzdWx0IGFzIGFuIGFycmF5IG9mIGhhc2hlcy4KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKc3ViIHJ1bl9xdWVyeSB7CglteSAkd3FsX3F1ZXJ5ID0gJF9bMF07CglteSBAcmVzdWx0ID0ge307CgoJJHdxbF9xdWVyeSA9fiAncy8iL1wnL2cnOwoKCSMgUnVuIHRoZSBEQ09NL1dNSSBjbGllbnQKCW15ICRvdXRwdXQgPSBgJHdtaV9jbGllbnQgLVUgJyR1c2VybmFtZSclJyRwYXNzd29yZCcgLy8kdGFyZ2V0X2lwIFwiJHdxbF9xdWVyeVwiIDI+L2Rldi9udWxsYDsKCglteSBAbGluZXMgPSBzcGxpdCgvXG4vLCAkb3V0cHV0KTsKCSMgSGVhZGVyLCBkZXNjcmlwdGlvbiwgcmVzdWx0cwoJaWYgKCQjbGluZXMgPCAyKSB7CgkJZXhpdCAxOwoJfQoJIyBEcm9wIHRoZSBoZWFkZXIKCXNoaWZ0IChAbGluZXMpOwoJCQoJIyBHZXQgY29sdW1uIG5hbWVzCglteSBAY29sdW1uX25hbWVzID0gc3BsaXQoL1x8Lywgc2hpZnQgKEBsaW5lcykpOwoKCSMgR2V0IHJvdyBkYXRhCglteSAkaWR4ID0gMDsKCWZvciAobXkgJGkgPSAwOyAkaSA8PSAkI2xpbmVzOyAkaSsrKSB7CgkJIyBDaGVjayBmb3IgZXJyb3JzCgkJaWYgKCRsaW5lc1skaV0gPX4gbS9eRVJST1IvKSB7CgkJCWV4aXQgMTsKCQl9CgoJCSMgQmxhY2sgbGlzdAoJCWlmICgkbGluZXNbJGldID1+IG0vRmlsZSAxLykgewoJCQluZXh0OwoJCX0KCQlteSBAY29sdW1uID0gc3BsaXQoL1x8LywgJGxpbmVzWyRpXSk7CgkJZm9yIChteSAkaiA9IDA7ICRqIDw9ICQjY29sdW1uX25hbWVzOyAkaisrKSB7CgkJCWlmICghIGRlZmluZWQoJGNvbHVtblskal0pKSB7CgkJCQkkcmVzdWx0WyRpZHhdLT57JGNvbHVtbl9uYW1lc1skal19ID0gIiI7CgkJCX0KCQkJZWxzZSB7CgkJCQkkcmVzdWx0WyRpZHhdLT57JGNvbHVtbl9uYW1lc1skal19ID0gJGNvbHVtblskal07CgkJCX0KCQl9CgkJCgkJJGlkeCsrOwoJfQoJCglyZXR1cm4gQHJlc3VsdDsKfQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBTVUIgcHJpbnRfbW9kdWxlZGF0YSAoJG1vZHVsZV9pdGVtLCAkbW9kdWxlX2RhdGEsIAojICRtb2R1bGVfZGVzY3JpcHRpb24sIEBkYXRhKQojIFByaW50cyBhIG1vZHVsZWRhdGEgWE1MIHRhZy4gJG1vZHVsZV9pdGVtLCAkbW9kdWxlX2RhdGEgYW5kCiMgJG1vZHVsZV9kZXNjcmlwdGlvbiBhcmUgdXNlZCB0byBpbmRleCB0aGUgaXRlbSwgZGF0YSBhbmQgZGVzY3JpcHRpb24KIyBYTUwgdGFncyByZXNwZWN0aXZlbHkuCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCnN1YiBwcmludF9tb2R1bGVkYXRhIHsKCW15IEBtb2R1bGVfaGVhZGVycyA9IEB7JF9bMF19OwoJbXkgQG1vZHVsZV91bml0cyAgID0gQHskX1sxXX07CglteSBAZGF0YSAgICAgICAgICAgPSBAeyRfWzJdfTsKCW15ICRyZXN1bHQ7Cglmb3JlYWNoIG15ICRlbGVtZW50IChAZGF0YSkgewoJCSRyZXN1bHQgPSAnJzsKCQlmb3IgKCRpPTA7ICRpPEBtb2R1bGVfaGVhZGVyczskaSsrKSB7CgkJCWlmIChkZWZpbmVkICgkZWxlbWVudC0+eyRtb2R1bGVfaGVhZGVyc1skaV19KSkgewoJCQkJJHJlc3VsdCAuPSAkZWxlbWVudC0+eyRtb2R1bGVfaGVhZGVyc1skaV19IC4gJG1vZHVsZV91bml0c1skaV0gLiAnOyc7CgkJCX0KCQkJZWxzZSB7CgkJCQkkcmVzdWx0IC49ICc7JzsKCQkJfQoJCX0KCQljaG9wKCRyZXN1bHQpOwoJCXByaW50ICRyZXN1bHQgLiAiXG4iOwkKCX0KfQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBNYWluCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgpteSBAcmVzdWx0ICA9IHJ1bl9xdWVyeSgiU2VsZWN0IFNlcmlhbE51bWJlciBmcm9tIFdpbjMyX09wZXJhdGluZ1N5c3RlbSIpOwojIFJlbWVtYmVyIHRvIG1hdGNoIGxlbmdodCBvZiBib3RoIGFycmF5cyBoZWFkZXJzICYgdW5pdHMKbXkgQGhlYWRlcnMgPSAoIlNlcmlhbE51bWJlciIpOwpteSBAdW5pdHMgICA9ICgiIik7CnByaW50X21vZHVsZWRhdGEgKFxAaGVhZGVycyxcQHVuaXRzLCBcQHJlc3VsdCk7CmV4aXQgMDsKCg==' and `name` = 'product_ID' and `id_module_inventory`=36; +ALTER TABLE `tusuario` ADD COLUMN `api_token` VARCHAR(255) NOT NULL DEFAULT ''; + COMMIT; diff --git a/pandora_console/godmode/setup/setup_visuals.php b/pandora_console/godmode/setup/setup_visuals.php index cc038fc81c..afc79e3f01 100755 --- a/pandora_console/godmode/setup/setup_visuals.php +++ b/pandora_console/godmode/setup/setup_visuals.php @@ -1314,7 +1314,7 @@ $row++; $decimal_separators = [ ',' => ',', - '.' => '.' + '.' => '.', ]; $table_other->data[$row][0] = __('Decimal separator'); diff --git a/pandora_console/godmode/users/configure_user.php b/pandora_console/godmode/users/configure_user.php index 4cb44067fb..a217718960 100644 --- a/pandora_console/godmode/users/configure_user.php +++ b/pandora_console/godmode/users/configure_user.php @@ -42,10 +42,7 @@ require_once $config['homedir'].'/include/functions_visual_map.php'; require_once $config['homedir'].'/include/functions_custom_fields.php'; enterprise_include_once('include/functions_profile.php'); -$meta = false; -if (enterprise_installed() && defined('METACONSOLE')) { - $meta = true; -} +$meta = is_metaconsole(); $isFunctionSkins = enterprise_include_once('include/functions_skins.php'); @@ -55,12 +52,11 @@ if (ENTERPRISE_NOT_HOOK !== enterprise_include('include/functions_policies.php') $enterprise_include = true; } -if ($enterprise_include) { +if ($enterprise_include === true) { enterprise_include_once('meta/include/functions_users_meta.php'); } - -if (!is_metaconsole()) { +if (is_metaconsole() === false) { date_default_timezone_set('UTC'); include 'include/javascript/timezonepicker/includes/parser.inc'; @@ -110,13 +106,13 @@ if (!is_metaconsole()) { // This defines the working user. Beware with this, old code get confusses // and operates with current logged user (dangerous). $id = get_parameter('id', get_parameter('id_user', '')); -// ID given as parameter +// ID given as parameter. $pure = get_parameter('pure', 0); $user_info = get_user_info($id); $is_err = false; -if (! check_acl($config['id_user'], 0, 'UM')) { +if ((bool) check_acl($config['id_user'], 0, 'UM') === false) { db_pandora_audit( AUDIT_LOG_ACL_VIOLATION, 'Trying to access User Management' @@ -126,11 +122,11 @@ if (! check_acl($config['id_user'], 0, 'UM')) { return; } -if (is_ajax()) { +if (is_ajax() === true) { $delete_profile = (bool) get_parameter('delete_profile'); $get_user_profile = (bool) get_parameter('get_user_profile'); - if ($delete_profile) { + if ($delete_profile === true) { $id2 = (string) get_parameter('id_user'); $id_up = (int) get_parameter('id_user_profile'); @@ -160,7 +156,7 @@ if (is_ajax()) { if ($has_profile === false && $user_is_global_admin === false) { $result = delete_user($id2); - if ($result) { + if ($result === true) { db_pandora_audit( AUDIT_LOG_USER_MANAGEMENT, __('Deleted user %s', io_safe_output($id_user)) @@ -173,30 +169,34 @@ if (is_ajax()) { __('There was a problem deleting the user') ); - // Delete the user in all the consoles - if (defined('METACONSOLE')) { + // Delete the user in all the consoles. + if (is_metaconsole() === true) { $servers = metaconsole_get_servers(); foreach ($servers as $server) { - // Connect to the remote console + // Connect to the remote console. metaconsole_connect($server); - // Delete the user + // Delete the user. $result = delete_user($id_user); - if ($result) { + if ($result === true) { db_pandora_audit( AUDIT_LOG_USER_MANAGEMENT, __('Deleted user %s from metaconsole', io_safe_output($id_user)) ); } - // Restore the db connection + // Restore the db connection. metaconsole_restore_db(); - // Log to the metaconsole too - if ($result) { + // Log to the metaconsole too. + if ($result === true) { db_pandora_audit( AUDIT_LOG_USER_MANAGEMENT, - __('Deleted user %s from %s', io_safe_input($id_user), io_safe_input($server['server_name'])) + __( + 'Deleted user %s from %s', + io_safe_input($id_user), + io_safe_input($server['server_name']) + ) ); } @@ -272,14 +272,8 @@ enterprise_hook('open_meta_frame'); $tab = get_parameter('tab', 'user'); -if ($id) { - $header_title = ' » '.__('Update user'); -} else { - $header_title = ' » '.__('Create user'); -} - -// Header -if ($meta) { +// Header. +if (is_metaconsole() === true) { user_meta_print_header(); $sec = 'advanced'; } else { @@ -310,19 +304,34 @@ if ($meta) { $buttons[$tab]['active'] = true; - ui_print_page_header( - __('User detail editor').$header_title, + ui_print_standard_header( + (empty($id) === false) ? __('Update user') : __('Create user'), 'images/gm_users.png', false, '', true, - $buttons + $buttons, + [ + [ + 'link' => '', + 'label' => __('Profiles'), + ], + [ + 'link' => ui_get_full_url('index.php?sec=gusuarios&sec2=godmode/users/user_list'), + 'label' => __('Manage users'), + ], + [ + 'link' => '', + 'label' => __('User Detail Editor'), + ], + ] ); + $sec = 'gusuarios'; } -if ($config['user_can_update_info']) { +if ((bool) $config['user_can_update_info'] === true) { $view_mode = false; } else { $view_mode = true; @@ -332,17 +341,18 @@ $new_user = (bool) get_parameter('new_user'); $create_user = (bool) get_parameter('create_user'); $add_profile = (bool) get_parameter('add_profile'); $update_user = (bool) get_parameter('update_user'); +$renewAPIToken = (bool) get_parameter('renewAPIToken'); $status = get_parameter('status', -1); $json_profile = get_parameter('json_profile', ''); -// Reset status var if current action is not update_user -if ($new_user || $create_user || $add_profile - || $delete_profile || $update_user +// Reset status var if current action is not update_user. +if ($new_user === true || $create_user === true || $add_profile === true + || $delete_profile === true || $update_user === true ) { $status = -1; } -if ($new_user && $config['admin_can_add_user']) { +if ($new_user === true && (bool) $config['admin_can_add_user'] === true) { $user_info = []; $id = ''; $user_info['fullname'] = ''; @@ -366,28 +376,30 @@ if ($new_user && $config['admin_can_add_user']) { $user_info['section'] = ''; $user_info['data_section'] = ''; - // This attributes are inherited from global configuration + // This attributes are inherited from global configuration. $user_info['block_size'] = $config['block_size']; - if (enterprise_installed() && is_metaconsole() === true) { + if (enterprise_installed() === true && is_metaconsole() === true) { $user_info['metaconsole_agents_manager'] = 0; $user_info['metaconsole_access_node'] = 0; } - if ($config['ehorus_user_level_conf']) { + if ((bool) $config['ehorus_user_level_conf'] === true) { $user_info['ehorus_user_level_user'] = ''; $user_info['ehorus_user_level_pass'] = ''; $user_info['ehorus_user_level_enabled'] = true; } } -if ($create_user) { - if (! $config['admin_can_add_user']) { - ui_print_error_message(__('The current authentication scheme doesn\'t support creating users on %s', get_product_name())); +if ($create_user === true) { + if ((bool) $config['admin_can_add_user'] === false) { + ui_print_error_message( + __('The current authentication scheme doesn\'t support creating users on %s', get_product_name()) + ); return; } - if (html_print_csrf_error()) { + if (html_print_csrf_error() === true) { return; } @@ -468,6 +480,8 @@ if ($create_user) { } } + // Generate new API token. + $values['api_token'] = api_token_generate(); if (empty($id) === true) { ui_print_error_message(__('User ID cannot be empty')); @@ -659,7 +673,7 @@ if ($create_user) { } if ($update_user) { - if (html_print_csrf_error()) { + if (html_print_csrf_error() === true) { return; } @@ -678,6 +692,9 @@ if ($update_user) { $values['timezone'] = (string) get_parameter('timezone'); $values['default_event_filter'] = (int) get_parameter('default_event_filter'); $values['default_custom_view'] = (int) get_parameter('default_custom_view'); + // API Token information. + $apiTokenRenewed = (bool) get_parameter('renewAPIToken'); + $values['api_token'] = ($apiTokenRenewed === true) ? api_token_generate() : users_get_API_token($values['id_user']); if (users_is_admin() === false && (bool) $values['is_admin'] !== false) { db_pandora_audit( @@ -689,7 +706,7 @@ if ($update_user) { exit; } - // eHorus user level conf. + // Ehorus user level conf. $values['ehorus_user_level_enabled'] = (bool) get_parameter('ehorus_user_level_enabled', false); $values['ehorus_user_level_user'] = (string) get_parameter('ehorus_user_level_user'); $values['ehorus_user_level_pass'] = (string) get_parameter('ehorus_user_level_pass'); @@ -868,7 +885,7 @@ if ($update_user) { ui_print_result_message( $res1, - __('User info successfully updated'), + ($apiTokenRenewed === true) ? __('You have generated a new API Token.') : __('User info successfully updated'), __('Error updating user info (no change?)') ); } @@ -904,7 +921,7 @@ if ($update_user) { $user_info = $values; } -if ($status != -1) { +if ((int) $status !== -1) { ui_print_result_message( $status, __('User info successfully updated'), @@ -1029,6 +1046,48 @@ if (!$new_user) { $user_id .= ''.$id.''; $user_id .= html_print_input_hidden('id_user', $id, true); $user_id .= ''; + $user_id .= '

'.__('API Token').'

'; + $user_id .= html_print_anchor( + [ + 'onClick' => sprintf( + 'javascript:renewAPIToken(\'%s\', \'%s\', \'%s\')', + __('Warning'), + __('The API token will be renewed. After this action, the last token you were using will not work. Are you sure?'), + 'user_profile_form', + ), + 'content' => html_print_image( + 'images/icono-refrescar.png', + true, + [ + 'class' => 'renew_api_token_image clickable', + 'title' => __('Renew API Token'), + ] + ), + 'class' => 'renew_api_token_link', + ], + true + ); + + $user_id .= html_print_anchor( + [ + 'onClick' => sprintf( + 'javascript:showAPIToken(\'%s\', \'%s\')', + __('API Token'), + base64_encode(__('Your API Token is:').' 
'.users_get_API_token($id).'
 '.__('Please, avoid share this string with others.')), + ), + 'content' => html_print_image( + 'images/eye_show.png', + true, + [ + 'class' => 'renew_api_token_image clickable', + 'title' => __('Show API Token'), + ] + ), + 'class' => 'renew_api_token_link', + ], + true + ); + $user_id .= '
'; } else { $user_id = '
'.html_print_input_text_extended( 'id_user', @@ -1047,7 +1106,7 @@ if (!$new_user) { ).'
'; } -if (is_user_admin($id)) { +if (is_user_admin($id) === true) { $avatar = html_print_image( 'images/people_1.png', true, @@ -1444,7 +1503,6 @@ $session_time .= html_print_input_text( 'class="input_line_small"' ).''; - $user_groups = implode(',', array_keys((users_get_groups($id, 'AR', $display_all_group)))); if (empty($user_groups) === false) { @@ -1573,7 +1631,7 @@ if (!$id) { $user_id_create = $user_id; } -if (is_metaconsole()) { +if (is_metaconsole() === true) { $access_or_pagination = $meta_access; } else { $access_or_pagination = $size_pagination; @@ -1589,14 +1647,14 @@ if ($id != '' && !$is_err) { echo '
- +

Extra info

'.$email.$phone.$not_login.$local_user.$session_time.'
-
+
'.$language.$access_or_pagination.$skin.$home_screen.$default_event_filter.$double_authentication.'
'.$timezone; -if (!is_metaconsole()) { +if (is_metaconsole() === false) { echo '
diff --git a/pandora_console/include/api.php b/pandora_console/include/api.php index cb3dae8e72..c0ee23e172 100644 --- a/pandora_console/include/api.php +++ b/pandora_console/include/api.php @@ -14,7 +14,7 @@ * |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______| * * ============================================================================ - * Copyright (c) 2005-2021 Artica Soluciones Tecnologicas + * Copyright (c) 2005-2022 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 @@ -69,9 +69,6 @@ $id2 = get_parameter('id2'); $otherSerialize = get_parameter('other'); $otherMode = get_parameter('other_mode', 'url_encode'); $returnType = get_parameter('return_type', 'string'); -$api_password = get_parameter('apipass', ''); -$password = get_parameter('pass', ''); -$user = get_parameter('user', ''); $info = get_parameter('info', ''); $raw_decode = (bool) get_parameter('raw_decode', false); @@ -84,6 +81,21 @@ $apiPassword = io_output_password( ) ); +$apiTokenValid = false; +// Try getting bearer token from header. +// TODO. Getting token from url will be removed. +$apiToken = (string) getBearerToken(); +if (empty($apiToken) === true) { + // Legacy user/pass token. + // TODO. Revome in future. + $api_password = get_parameter('apipass', ''); + $user = get_parameter('user', ''); + $password = get_parameter('pass', ''); +} else { + $apiTokenValid = (bool) api_token_check($apiToken); +} + + $correctLogin = false; $no_login_msg = ''; @@ -94,8 +106,8 @@ ob_clean(); // Special call without checks to retrieve version and build of the Pandora FMS // This info is avalable from the web console without login // Don't change the format, it is parsed by applications. -if ($info == 'version') { - if (!$config['MR']) { +if ($info === 'version') { + if ((bool) $config['MR'] === false) { $config['MR'] = 0; } @@ -105,6 +117,7 @@ if ($info == 'version') { if (empty($apiPassword) === true || (empty($apiPassword) === false && $api_password === $apiPassword) + || $apiTokenValid === true ) { if (enterprise_hook('metaconsole_validate_origin', [get_parameter('server_auth')]) === true || enterprise_hook('console_validate_origin', [get_parameter('server_auth')]) === true @@ -118,7 +131,14 @@ if (empty($apiPassword) === true $correctLogin = true; } else if ((bool) isInACL($ipOrigin) === true) { // External access. - $user_in_db = process_user_login($user, $password, true); + // Token is valid. Bypass the credentials. + if ($apiTokenValid === true) { + $credentials = db_get_row('tusuario', 'api_token', $apiToken); + $user = $credentials['id_user']; + $password = $credentials['password']; + } + + $user_in_db = process_user_login($user, $password, true, $apiTokenValid); if ($user_in_db !== false) { $config['id_usuario'] = $user_in_db; // Compat. @@ -144,19 +164,19 @@ if (empty($apiPassword) === true $no_login_msg = 'Incorrect given API password'; } -if ($correctLogin) { +if ($correctLogin === true) { if (($op !== 'get') && ($op !== 'set') && ($op !== 'help')) { returnError('no_set_no_get_no_help', $returnType); } else { $function_name = ''; // Check if is an extension function and get the function name. - if ($op2 == 'extension') { + if ($op2 === 'extension') { $extension_api_url = $config['homedir'].'/'.EXTENSIONS_DIR.'/'.$ext_name.'/'.$ext_name.'.api.php'; // The extension API file must exist and the extension must be // enabled. - if (file_exists($extension_api_url) - && !in_array($ext_name, extensions_get_disabled_extensions()) + if (file_exists($extension_api_url) === true + && in_array($ext_name, extensions_get_disabled_extensions()) === false ) { include_once $extension_api_url; $function_name = 'apiextension_'.$op.'_'.$ext_function; @@ -164,7 +184,7 @@ if ($correctLogin) { } else { $function_name = 'api_'.$op.'_'.$op2; - if ($op == 'set' && $id) { + if ($op === 'set' && $id) { switch ($op2) { case 'update_agent': case 'add_module_in_conf': @@ -173,7 +193,7 @@ if ($correctLogin) { $agent = agents_locate_agent($id); if ($agent !== false) { $id_os = $agent['id_os']; - if ($id_os == 100) { + if ((int) $id_os === 100) { returnError( 'not_allowed_operation_cluster', $returnType diff --git a/pandora_console/include/auth/mysql.php b/pandora_console/include/auth/mysql.php index a2c1ded77d..be845f3fc0 100644 --- a/pandora_console/include/auth/mysql.php +++ b/pandora_console/include/auth/mysql.php @@ -94,7 +94,7 @@ $config['admin_can_make_admin'] = true; * @return mixed False in case of error or invalid credentials, the username in * case it's correct. */ -function process_user_login($login, $pass, $api=false) +function process_user_login($login, $pass, $api=false, $passAlreadyEncrypted=false) { global $config; @@ -130,10 +130,10 @@ function process_user_login($login, $pass, $api=false) if ($config['fallback_local_auth'] || is_user_admin($login) || $local_user === true - || strtolower($config['auth']) == 'mysql' + || strtolower($config['auth']) === 'mysql' || (bool) $user_not_login === true ) { - return process_user_login_local($login, $pass, $api); + return process_user_login_local($login, $pass, $api, $passAlreadyEncrypted); } else { return false; } @@ -144,12 +144,11 @@ function process_user_login($login, $pass, $api=false) } -function process_user_login_local($login, $pass, $api=false) +function process_user_login_local($login, $pass, $api=false, $passAlreadyEncrypted=false) { global $config, $mysql_cache; - // Connect to Database. - if (!$api) { + if ((bool) $api === false) { $sql = sprintf( "SELECT `id_user`, `password` FROM `tusuario` @@ -169,13 +168,17 @@ function process_user_login_local($login, $pass, $api=false) $row = db_get_row_sql($sql); - // Perform password check whether it is MD5-hashed (old hashing) or Bcrypt-hashed. - if (strlen($row['password']) === 32) { - // MD5. - $credentials_check = $row !== false && $row['password'] !== md5('') && $row['password'] == md5($pass); + if ($passAlreadyEncrypted) { + $credentials_check = $pass === $row['password']; } else { - // Bcrypt. - $credentials_check = password_verify($pass, $row['password']); + // Perform password check whether it is MD5-hashed (old hashing) or Bcrypt-hashed. + if (strlen($row['password']) === 32) { + // MD5. + $credentials_check = $row !== false && $row['password'] !== md5('') && $row['password'] == md5($pass); + } else { + // Bcrypt. + $credentials_check = password_verify($pass, $row['password']); + } } if ($credentials_check === true) { @@ -184,10 +187,10 @@ function process_user_login_local($login, $pass, $api=false) // is not case sensitive) // We get DB nick to put in PHP Session variable, // to avoid problems with case-sensitive usernames. - // Thanks to David Muñiz for Bug discovery :) + // Thanks to David Muñiz for Bug discovery :). $filter = ['id_usuario' => $login]; $user_profile = db_get_row_filter('tusuario_perfil', $filter); - if (!users_is_admin($login) && !$user_profile) { + if ((bool) users_is_admin($login) === false && (bool) $user_profile === false) { $mysql_cache['auth_error'] = 'User does not have any profile'; $config['auth_error'] = 'User does not have any profile'; return false; @@ -200,7 +203,7 @@ function process_user_login_local($login, $pass, $api=false) return $row['id_user']; } else { - if (!user_can_login($login)) { + if (user_can_login($login) === false) { $mysql_cache['auth_error'] = 'User only can use the API.'; $config['auth_error'] = 'User only can use the API.'; } else { diff --git a/pandora_console/include/functions.php b/pandora_console/include/functions.php index 7c2df5603b..43fef71ced 100644 --- a/pandora_console/include/functions.php +++ b/pandora_console/include/functions.php @@ -6326,7 +6326,7 @@ function arrayOutputSorting($sort, $sortField) /** * Get dowload started cookie from js and set ready cokkie for download ready comntrol. * - * @return + * @return void */ function setDownloadCookieToken() { @@ -6342,3 +6342,48 @@ function setDownloadCookieToken() ); } } + + +/** + * Get header Authorization + * */ +function getAuthorizationHeader() +{ + $headers = null; + if (isset($_SERVER['Authorization'])) { + $headers = trim($_SERVER['Authorization']); + } else if (isset($_SERVER['HTTP_AUTHORIZATION'])) { + // Nginx or fast CGI + $headers = trim($_SERVER['HTTP_AUTHORIZATION']); + } else if (function_exists('apache_request_headers')) { + $requestHeaders = apache_request_headers(); + // Server-side fix for bug in old Android versions (a nice side-effect of this fix means we don't care about capitalization for Authorization) + $requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders)); + // print_r($requestHeaders); + if (isset($requestHeaders['Authorization'])) { + $headers = trim($requestHeaders['Authorization']); + } + } + + return $headers; +} + + +/** + * Get access token from header + * + * @return array/false Token received, false in case thre is no token. + * */ +function getBearerToken() +{ + $headers = getAuthorizationHeader(); + + // HEADER: Get the access token from the header + if (!empty($headers)) { + if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) { + return $matches[1]; + } + } + + return false; +} diff --git a/pandora_console/include/functions_api.php b/pandora_console/include/functions_api.php index db79ed3c86..d141160f9b 100644 --- a/pandora_console/include/functions_api.php +++ b/pandora_console/include/functions_api.php @@ -17648,3 +17648,20 @@ function api_set_send_report($thrash1, $thrash2, $other, $returnType) returnData($returnType, $data, ';'); } } + + +/** + * Check if token is correct. + * + * @param string $token Token for check. + * + * @return mixed Id of user. If returns 0 there is not valid token. + */ +function api_token_check(string $token) +{ + if (empty($token) === true) { + return 0; + } else { + return db_get_value('id_user', 'tusuario', 'api_token', $token); + } +} diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php index 52ad703edd..798c8cf72a 100755 --- a/pandora_console/include/functions_ui.php +++ b/pandora_console/include/functions_ui.php @@ -2370,13 +2370,17 @@ function ui_print_help_tip( $return=false, $img='images/tip_help.png', $is_relative=false, - $style='' + $style='', + $blink=false ) { $output = ''; $output .= html_print_image( $img, true, - ['title' => $text], + [ + 'title' => $text, + 'class' => $blink === true ? 'blink' : '', + ], false, $is_relative && is_metaconsole() ).''; diff --git a/pandora_console/include/functions_users.php b/pandora_console/include/functions_users.php index 17dc7911ee..ad3e6ac3b2 100755 --- a/pandora_console/include/functions_users.php +++ b/pandora_console/include/functions_users.php @@ -884,6 +884,69 @@ function users_get_users_group_by_group($id_group) } +/** + * Generates a cryptographically secure chain for use with API. + * + * @return string + */ +function api_token_generate() +{ + include_once 'functions_api.php'; + // Generate a cryptographically secure chain. + $generateToken = bin2hex(openssl_random_pseudo_bytes(16)); + // Check if token exists in DB. + $tokenExists = (bool) api_token_check($generateToken); + // If not exists, can be assigned. In other case, try again. + return ($tokenExists === false) ? $generateToken : api_token_generate(); +} + + +/** + * Returns User API Token + * + * @param string $idUser Id of the user. + * + * @return string + */ +function users_get_API_token(string $idUser) +{ + $output = db_get_value('api_token', 'tusuario', 'id_user', $idUser); + + if (empty($output) === true) { + $output = '<< '.__('NONE').' >>'; + } + + return $output; +} + + +/** + * Renews the API Token. + * + * @param integer $idUser Id of the user. + * + * @return boolean Return true if the token was renewed. + */ +function users_renew_API_token(int $idUser) +{ + $apiToken = api_token_generate(); + + if (empty($apiToken) === false) { + $result = db_process_sql_update( + 'tusuario', + ['api_token' => $apiToken], + ['id_user' => $idUser] + ); + + if ($result !== false) { + return true; + } + } + + return false; +} + + /** * Check if IP is in range. Check wildcard `*`, single IP and IP ranges. * diff --git a/pandora_console/include/javascript/pandora.js b/pandora_console/include/javascript/pandora.js index 03a2ec8fe3..4a427caeff 100644 --- a/pandora_console/include/javascript/pandora.js +++ b/pandora_console/include/javascript/pandora.js @@ -2185,6 +2185,38 @@ $.fn.filterByText = function(textbox) { }); }; +/** + * Confirm Dialog for API token renewal request. + * + * @param {string} title Title for show. + * @param {string} message Message for show. + * @param {string} form Form to attach renewAPIToken element. + */ +function renewAPIToken(title, message, form) { + confirmDialog({ + title: title, + message: message, + onAccept: function() { + $("#" + form) + .append("") + .submit(); + } + }); +} + +/** + * Show Dialog for view the API token. + * + * @param {string} title Title for show. + * @param {string} message Base64 encoded message for show. + */ +function showAPIToken(title, message) { + confirmDialog({ + title: title, + message: atob(message), + hideCancelButton: true + }); +} function loadPasswordConfig(id, value) { $.ajax({ url: "ajax.php", diff --git a/pandora_console/include/lib/ClusterViewer/ClusterManager.php b/pandora_console/include/lib/ClusterViewer/ClusterManager.php index 884be3f2a7..c7e0385fa6 100644 --- a/pandora_console/include/lib/ClusterViewer/ClusterManager.php +++ b/pandora_console/include/lib/ClusterViewer/ClusterManager.php @@ -105,7 +105,6 @@ class ClusterManager */ public function run() { - $operation = get_parameter('op', ''); switch ($operation) { @@ -329,10 +328,8 @@ class ClusterManager */ public function showClusterEditor(string $operation) { - global $config; if (!check_acl($config['id_user'], 0, 'AW')) { - db_pandora_audit( AUDIT_LOG_ACL_VIOLATION, 'Trying to create clusters' diff --git a/pandora_console/include/lib/Dashboard/Manager.php b/pandora_console/include/lib/Dashboard/Manager.php index f22aa7a4f0..fed596e08e 100644 --- a/pandora_console/include/lib/Dashboard/Manager.php +++ b/pandora_console/include/lib/Dashboard/Manager.php @@ -818,9 +818,9 @@ class Manager implements PublicLogin $string_groups = io_safe_output($string_groups); $sql_dashboard = sprintf( - "SELECT COUNT(*) + 'SELECT COUNT(*) FROM tdashboard - WHERE (id_group IN (%s))", + WHERE (id_group IN (%s))', $string_groups ); } else { diff --git a/pandora_console/include/rest-api/models/VisualConsole/Container.php b/pandora_console/include/rest-api/models/VisualConsole/Container.php index b4bc3ae2ed..d8042c8054 100644 --- a/pandora_console/include/rest-api/models/VisualConsole/Container.php +++ b/pandora_console/include/rest-api/models/VisualConsole/Container.php @@ -553,4 +553,6 @@ final class Container extends Model return $item; } + + } diff --git a/pandora_console/include/rest-api/models/VisualConsole/Item.php b/pandora_console/include/rest-api/models/VisualConsole/Item.php index b6fb740c3c..afdb679b97 100644 --- a/pandora_console/include/rest-api/models/VisualConsole/Item.php +++ b/pandora_console/include/rest-api/models/VisualConsole/Item.php @@ -2724,4 +2724,6 @@ class Item extends CachedModel return false; } + + } diff --git a/pandora_console/include/styles/pandora.css b/pandora_console/include/styles/pandora.css index f67f840744..b5ade74fc0 100644 --- a/pandora_console/include/styles/pandora.css +++ b/pandora_console/include/styles/pandora.css @@ -4678,6 +4678,21 @@ input:checked + .p-slider:before { animation: fadein 0.5s, fadeout 0.5s 7.5s; } +.blink { + animation: blink-animation 1s steps(5, start) infinite; + -webkit-animation: blink-animation 1s steps(5, start) infinite; +} +@keyframes blink-animation { + to { + visibility: hidden; + } +} +@-webkit-keyframes blink-animation { + to { + visibility: hidden; + } +} + .snackbar p, .snackbar h3 { text-align: left; @@ -9065,6 +9080,14 @@ div#err_msg_centralised { width: 75%; } +.renew_api_token_link { + margin: 3px 0.5em 0 0; + float: right; +} + +.renew_api_token_image { + width: 16px; +} @media screen and (max-width: 1369px) { .div-col { width: 50%; diff --git a/pandora_console/operation/cluster/cluster.php b/pandora_console/operation/cluster/cluster.php index 2cc078ef4b..e9a2ec98c5 100755 --- a/pandora_console/operation/cluster/cluster.php +++ b/pandora_console/operation/cluster/cluster.php @@ -37,7 +37,6 @@ $ajaxPage = 'operation/cluster/cluster'; // Control call flow. try { - // User access and validation is being processed on class constructor. $obj = new ClusterManager($ajaxPage); } catch (Exception $e) { diff --git a/pandora_console/operation/users/user_edit.php b/pandora_console/operation/users/user_edit.php index c1f2e1fee2..f77a5dfa49 100644 --- a/pandora_console/operation/users/user_edit.php +++ b/pandora_console/operation/users/user_edit.php @@ -83,9 +83,12 @@ if (isset($_GET['modified']) && !$view_mode) { $upd_info['id_skin'] = get_parameter('skin', $user_info['id_skin']); $upd_info['default_event_filter'] = get_parameter('event_filter', null); $upd_info['block_size'] = get_parameter('block_size', $config['block_size']); + // API Token information. + $apiTokenRenewed = (bool) get_parameter('renewAPIToken'); + $upd_info['api_token'] = ($apiTokenRenewed === true) ? api_token_generate() : users_get_API_token($config['id_user']); $default_block_size = get_parameter('default_block_size', 0); - if ($default_block_size) { + if ($default_block_size > 0) { $upd_info['block_size'] = 0; } @@ -161,16 +164,16 @@ if (isset($_GET['modified']) && !$view_mode) { } else if ($password_new !== 'NON-INIT') { $error_msg = __('Passwords didn\'t match or other problem encountered while updating passwords'); } - } else if (empty($password_new) && empty($password_confirm)) { + } else if (empty($password_new) === true && empty($password_confirm) === true) { $return = true; - } else if (empty($password_new) || empty($password_confirm)) { + } else if (empty($password_new) === true || empty($password_confirm) === true) { $return = false; } // No need to display "error" here, because when no update is needed // (no changes in data) SQL function returns 0 (FALSE), but is not an error, // just no change. Previous error message could be confussing to the user. - if ($return) { + if ($return !== false) { if (empty($password_new) === false && empty($password_confirm) === false) { $success_msg = __('Password successfully updated'); } @@ -184,7 +187,11 @@ if (isset($_GET['modified']) && !$view_mode) { if ($return_update_user === false) { $error_msg = __('Error updating user info'); } else if ($return_update_user == true) { - $success_msg = __('User info successfully updated'); + if ($apiTokenRenewed === true) { + $success_msg = __('You have generated a new API Token.'); + } else { + $success_msg = __('User info successfully updated'); + } } else { if (empty($password_new) === false && empty($password_confirm) === false) { $success_msg = __('Password successfully updated'); @@ -226,7 +233,7 @@ if (isset($_GET['modified']) && !$view_mode) { } // Prints action status for current message. -if ($status != -1) { +if ((int) $status !== -1) { ui_print_result_message( $status, __('User info successfully updated'), @@ -261,6 +268,73 @@ if (is_metaconsole() === false && is_management_allowed() === false) { $user_id = '

'.__('User ID').':

'; $user_id .= ''.$id.'
'; +$user_id .= '

'.__('API Token').'

'; +if (is_management_allowed()) { + $user_id .= html_print_anchor( + [ + 'onClick' => sprintf( + 'javascript:renewAPIToken(\'%s\', \'%s\', \'%s\')', + __('Warning'), + __('The API token will be renewed. After this action, the last token you were using will not work. Are you sure?'), + 'user_profile_form', + ), + 'content' => html_print_image( + 'images/icono-refrescar.png', + true, + [ + 'class' => 'renew_api_token_image clickable', + 'title' => __('Renew API Token'), + ] + ), + 'class' => 'renew_api_token_link', + ], + true + ); +} + + +// Check php conf for header auth. +$lines = file('/etc/httpd/conf.d/php.conf'); +$http_authorization = false; + +foreach ($lines as $l) { + if (preg_match('/SetEnvIfNoCase \^Authorization\$ \"\(\.\+\)\" HTTP_AUTHORIZATION=\$1/', $l)) { + $http_authorization = true; + } +} + +$user_id .= html_print_anchor( + [ + 'onClick' => sprintf( + 'javascript:showAPIToken(\'%s\', \'%s\')', + __('API Token'), + base64_encode(__('Your API Token is:').'
'.users_get_API_token($config['id_user']).'
'.__('Please, avoid share this string with others.')), + ), + 'content' => html_print_image( + 'images/eye_show.png', + true, + [ + 'class' => 'renew_api_token_image clickable', + 'title' => __('Show API Token'), + ] + ), + 'class' => 'renew_api_token_link', + ], + true +); + +if ($http_authorization === false) { + $user_id .= ui_print_help_tip( + __('Directive HTTP_AUTHORIZATION=$1 is not set. Please, add it to /etc/httpd/conf.d/php.conf'), + true, + 'images/warn.png', + false, + '', + true + ); +} + +$user_id .= '
'; $full_name = '
'.html_print_input_text_extended( 'fullname', $user_info['fullname'], @@ -278,7 +352,7 @@ $full_name = '
'.html_print_input_text_extended ).'
'; // Show "Picture" (in future versions, why not, allow users to upload it's own avatar here. -if (is_user_admin($id)) { +if (is_user_admin($id) === true) { $avatar = html_print_image('images/people_1.png', true, ['class' => 'user_avatar']); } else { $avatar = html_print_image('images/people_2.png', true, ['class' => 'user_avatar']); @@ -654,10 +728,10 @@ foreach ($timezones as $timezone_name => $tz) { } } -if (is_metaconsole()) { - echo '
'; +if (is_metaconsole() === true) { + echo ''; } else { - echo ''; + echo ''; } html_print_input_hidden('id', $id, false, false, false, 'id'); diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index cc7cea5dff..3f90f157f8 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -1313,6 +1313,7 @@ CREATE TABLE IF NOT EXISTS `tusuario` ( `ehorus_user_level_enabled` TINYINT, `integria_user_level_user` VARCHAR(60), `integria_user_level_pass` VARCHAR(45), + `api_token` VARCHAR(255) NOT NULL DEFAULT '', `allowed_ip_active` TINYINT UNSIGNED DEFAULT 0, `allowed_ip_list` TEXT, `auth_token_secret` VARCHAR(45) DEFAULT NULL, diff --git a/pandora_console/pandoradb_data.sql b/pandora_console/pandoradb_data.sql index c962b6f3ff..e08deaea1d 100644 --- a/pandora_console/pandoradb_data.sql +++ b/pandora_console/pandoradb_data.sql @@ -344,8 +344,8 @@ INSERT INTO `tmodule_inventory` (`id_module_inventory`, `id_os`, `name`, `descri -- -- Dumping data for table `tusuario` -- -INSERT INTO `tusuario` (`id_user`, `fullname`, `firstname`, `lastname`, `middlename`, `password`, `comments`, `last_connect`, `registered`, `email`, `phone`, `is_admin`, `language`, `block_size`, `section`, `data_section`, `metaconsole_access`, `local_user`) VALUES -('admin', 'Pandora', 'Pandora', 'Admin', '', '$2y$10$Wv/xoxjI2VAkthJhk/PzeeGIhBKYU/K.TMgUdmW7fEP2NQkdWlB9K', 'Admin Pandora', 1232642121, 0, 'admin@example.com', '555-555-5555', 1, 'default', 0, 'Default', '', 'advanced', 1); +INSERT INTO `tusuario` (`id_user`, `fullname`, `firstname`, `lastname`, `middlename`, `password`, `comments`, `last_connect`, `registered`, `email`, `phone`, `is_admin`, `language`, `block_size`, `section`, `data_section`, `metaconsole_access`, `local_user`, `api_token`) VALUES +('admin', 'Pandora', 'Pandora', 'Admin', '', '$2y$10$Wv/xoxjI2VAkthJhk/PzeeGIhBKYU/K.TMgUdmW7fEP2NQkdWlB9K', 'Admin Pandora', 1232642121, 0, 'admin@example.com', '555-555-5555', 1, 'default', 0, 'Default', '', 'advanced', 1, 'pandora1234'); -- -- Dumping data for table `tusuario_perfil` diff --git a/pandora_console/views/cluster/view.php b/pandora_console/views/cluster/view.php index 1742930ad1..aa0c24fdf4 100644 --- a/pandora_console/views/cluster/view.php +++ b/pandora_console/views/cluster/view.php @@ -87,7 +87,8 @@ ui_print_page_header( [ 'active' => false, 'text' => $main_page, - ],[ + ], + [ 'active' => false, 'text' => $edit, ],